diff --git a/commands/i386/pc/checktime.c b/commands/i386/pc/checktime.c
new file mode 100644
index 0000000..a9d015c
--- /dev/null
+++ b/commands/i386/pc/checktime.c
@@ -0,0 +1,165 @@
+/* checktime.c - command to test current date/time. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+static int
+grub_cmd_checktime (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ grub_uint32_t date, time;
+ int day, month, year, sec, min, hour, dow, i;
+ int limit[5][2] = {{0, 59}, {0, 23}, {1, 31}, {1, 12}, {0, 7}};
+ int field[5];
+
+ auto int get_day_of_week (void);
+ int get_day_of_week (void)
+ {
+ int a, y, m;
+
+ a = (14 - month) / 12;
+ y = year - a;
+ m = month + 12 * a - 2;
+ return (day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7;
+ }
+
+ grub_get_datetime (&date, &time);
+
+ day = ((date >> 4) & 0xF) * 10 + (date & 0xF);
+ date >>= 8;
+
+ month = ((date >> 4) & 0xF) * 10 + (date & 0xF);
+ date >>= 8;
+
+ year = ((date >> 4) & 0xF) * 10 + (date & 0xF);
+ date >>= 8;
+ year += (((date >> 4) & 0xF) * 10 + (date & 0xF)) * 100;
+
+ time >>= 8;
+
+ sec = ((time >> 4) & 0xF) * 10 + (time & 0xF);
+ time >>= 8;
+
+ min = ((time >> 4) & 0xF) * 10 + (time & 0xF);
+ time >>= 8;
+
+ hour = ((time >> 4) & 0xF) * 10 + (time & 0xF);
+
+ dow = get_day_of_week ();
+
+ field[0] = min;
+ field[1] = hour;
+ field[2] = day;
+ field[3] = month;
+ field[4] = dow;
+
+ if (argc == 0)
+ {
+ grub_printf ("%d-%02d-%02d %02d:%02d:%02d %d\n",
+ year, month, day, hour, min, sec, dow);
+
+ return 0;
+ }
+
+ for (i = 0; i < 5; i++)
+ {
+ char *p;
+ int ok = 0;
+
+ if (i >= argc)
+ return 0;
+
+ p = args[i];
+ while (1)
+ {
+ int m1, m2, m3, j;
+
+ if (*p == '*')
+ {
+ m1 = limit[i][0];
+ m2 = limit[i][1];
+ p++;
+ }
+ else
+ {
+ m1 = grub_strtoul (p, &p, 0);
+
+ if (*p == '-')
+ {
+ p++;
+ m2 = grub_strtoul (p, &p, 0);
+ }
+ else
+ m2 = m1;
+ }
+
+ if ((m1 < limit[i][0]) || (m2 > limit[i][1]) || (m1 > m2))
+ break;
+
+ if (*p == '/')
+ {
+ p++;
+ m3 = grub_strtoul (p, &p, 0);
+ }
+ else
+ m3 = 1;
+
+ for (j = m1; j <= m2; j+= m3)
+ {
+ if (j == field[i])
+ {
+ ok = 1;
+ break;
+ }
+ }
+
+ if (ok)
+ break;
+
+ if (*p == ',')
+ p++;
+ else
+ break;
+ }
+
+ if (! ok)
+ break;
+ }
+
+ return (i == 5) ? 0 : grub_error (GRUB_ERR_TEST_FAILURE, "false");
+}
+
+GRUB_MOD_INIT(checktime)
+{
+ (void) mod; /* To stop warning. */
+ grub_register_command ("checktime", grub_cmd_checktime,
+ GRUB_COMMAND_FLAG_BOTH,
+ "checktime min hour day_of_month month day_of_week",
+ "Command to test current date/time.", 0);
+}
+
+GRUB_MOD_FINI(checktime)
+{
+ grub_unregister_command ("checktime");
+}
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index c1e4ac4..b9c8f35 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -55,7 +55,7 @@ kernel_img_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \
machine/memory.h machine/loader.h machine/vga.h machine/vbe.h \
- machine/kernel.h machine/pxe.h
+ machine/kernel.h machine/pxe.h machine/time.h
kernel_img_CFLAGS = $(COMMON_CFLAGS)
kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,$(GRUB_MEMORY_MACHINE_LINK_ADDR) $(COMMON_CFLAGS)
@@ -163,7 +163,7 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod \
ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod \
- aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod
+ aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod chktime.mod
# For biosdisk.mod.
biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -340,4 +340,9 @@ pxecmd_mod_SOURCES = commands/i386/pc/pxecmd.c
pxecmd_mod_CFLAGS = $(COMMON_CFLAGS)
pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For chktime.mod
+chktime_mod_SOURCES = commands/i386/pc/checktime.c
+chktime_mod_CFLAGS = $(COMMON_CFLAGS)
+chktime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/include/grub/i386/pc/time.h b/include/grub/i386/pc/time.h
index 98399b6..f41cc1d 100644
--- a/include/grub/i386/pc/time.h
+++ b/include/grub/i386/pc/time.h
@@ -26,4 +26,6 @@
/* Return the real time in ticks. */
grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void);
+void EXPORT_FUNC(grub_get_datetime) (grub_uint32_t *date, grub_uint32_t *time);
+
#endif /* ! KERNEL_MACHINE_TIME_HEADER */
diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S
index 197c447..0aecedd 100644
--- a/kern/i386/pc/startup.S
+++ b/kern/i386/pc/startup.S
@@ -2153,3 +2153,57 @@ FUNCTION(grub_pxe_call)
popl %esi
popl %ebp
ret
+
+/*
+ * void grub_get_datetime (grub_uint32_t *date,
+ * grub_uint32_t *time);
+ */
+FUNCTION(grub_get_datetime)
+ pushl %ebp
+ pushl %ebx
+
+ pushl %eax
+ pushl %edx
+
+ call prot_to_real
+ .code16
+
+ movb $2, %ah
+ clc
+ int $0x1a
+ jc 2f
+
+ pushw %cx
+ pushw %dx
+
+ movb $4, %ah
+ clc
+ int $0x1a
+ jc 3f
+
+ pushw %cx
+ pushw %dx
+ popl %edx
+ popl %ecx
+ jmp 1f
+
+3:
+ popl %eax
+
+2:
+ xorl %ecx, %ecx
+ xorl %edx, %edx
+
+1:
+ DATA32 call real_to_prot
+ .code32
+
+ popl %eax
+ movl %ecx, (%eax)
+
+ popl %eax
+ movl %edx, (%eax)
+
+ popl %ebx
+ popl %ebp
+ ret