* [PATCH] New command checktime
@ 2008-08-06 11:02 Bean
2008-08-06 11:35 ` Robert Millan
2008-08-10 18:04 ` Marco Gerards
0 siblings, 2 replies; 28+ messages in thread
From: Bean @ 2008-08-06 11:02 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 1588 bytes --]
Hi,
I implement this command for grub4dos some time ago, now it's ported to grub2.
Usage:
checktime min hour day_of_month month day_of_week
The five parameters for checktime is the same as in crontab: minute,
hour, day, month and day of week. This command check if the current
daytime is within the range specified by the parameters, and return
true or false accordingly. Combined this with the script support for
grub2, you can perform some operation in a selected time range.
The range of the five parameters are:
minute: 0-59
hour: 0-23
day of month: 1-31
month 1-12
day of week 0-6 (0 is Sunday)
checktime * 12-15 * 1,3-5 *
Return true on afternoon of Jan, March, April and May.
checktime * * * */2 *
Return true on Month 1,3,5,7,9,11
For example, you can use a different background image according to the
current season:
if checktime * * * 3-5 *; then
background_image /spring.png
fi
if checktime * * * 6-8 *; then
background_image /summer.png
fi
if checktime * * * 9-11 *; then
background_image /fall.png
fi
if checktime * * * 1-2,12 *; then
background_image /winter.png
fi
Or boot a different item in the morning, afternoon and evening.
2008-08-06 Bean <bean123ch@gmail.com>
* conf/i386-pc.rmk (kernel_img_HEADERS): Add machine/time.h.
(pkglib_MODULES): Add chktime.mod.
(chktime_mod_SOURCES): New macro.
(chktime_mod_CFLAGS): Likewise.
(chktime_mod_LDFLAGS): Likewise.
* include/grub/i386/pc/time.h: Add function grub_get_datetime.
* kern/i386/pc/startup.S: Add function grub_get_datetime.
* commands/i386/pc/checktime.c: New file.
--
Bean
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: checktime.diff --]
[-- Type: text/x-diff; name=checktime.diff, Size: 6958 bytes --]
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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/machine/time.h>
+
+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
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-06 11:02 [PATCH] New command checktime Bean
@ 2008-08-06 11:35 ` Robert Millan
2008-08-06 15:09 ` Bean
2008-08-10 18:04 ` Marco Gerards
1 sibling, 1 reply; 28+ messages in thread
From: Robert Millan @ 2008-08-06 11:35 UTC (permalink / raw)
To: The development of GRUB 2
On Wed, Aug 06, 2008 at 07:02:46PM +0800, Bean wrote:
> if checktime * * * 3-5 *; then
> background_image /spring.png
> fi
>
> if checktime * * * 6-8 *; then
> background_image /summer.png
> fi
>
> if checktime * * * 9-11 *; then
> background_image /fall.png
> fi
>
> if checktime * * * 1-2,12 *; then
> background_image /winter.png
> fi
Nifty :-)
> +FUNCTION(grub_get_datetime)
> + pushl %ebp
> + pushl %ebx
> +
> + pushl %eax
> + pushl %edx
> +
> + call prot_to_real
> + .code16
> +
> + movb $2, %ah
> + clc
> + int $0x1a
Can we make this portable by accessing 0x70 / 0x71 I/O ports instead?
--
Robert Millan
The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
how) you may access your data; but nobody's threatening your freedom: we
still allow you to remove your data and not access it at all."
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-06 11:35 ` Robert Millan
@ 2008-08-06 15:09 ` Bean
2008-08-06 19:57 ` Robert Millan
0 siblings, 1 reply; 28+ messages in thread
From: Bean @ 2008-08-06 15:09 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 613 bytes --]
On Wed, Aug 6, 2008 at 7:35 PM, Robert Millan <rmh@aybabtu.com> wrote:
> Can we make this portable by accessing 0x70 / 0x71 I/O ports instead?
Hi,
Good point. The new patch uses cmos to get datetime setting, it should
be generic among i386 platforms.
2008-08-06 Bean <bean123ch@gmail.com>
* conf/i386-pc.rmk (pkglib_MODULES): Add chktime.mod.
(chktime_mod_SOURCES): New macro.
(chktime_mod_CFLAGS): Likewise.
(chktime_mod_LDFLAGS): Likewise.
* commands/checktime.c: New file.
* include/grub/datetime.h: Likewise.
* include/grub/i386/cmos.h: Likewise.
* kern/i386/datetime.c: Likewise.
--
Bean
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: checktime_2.diff --]
[-- Type: text/x-diff; name=checktime_2.diff, Size: 10932 bytes --]
diff --git a/commands/checktime.c b/commands/checktime.c
new file mode 100644
index 0000000..6e3d0d9
--- /dev/null
+++ b/commands/checktime.c
@@ -0,0 +1,147 @@
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/i386/cmos.h>
+#include <grub/datetime.h>
+
+static grub_err_t
+grub_cmd_checktime (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ 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;
+ }
+
+ if ((grub_get_date (&year, &month, &day)) ||
+ (grub_get_time (&hour, &min, &sec)))
+ return grub_errno;
+
+ 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..f383160 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -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/checktime.c kern/i386/datetime.c
+chktime_mod_CFLAGS = $(COMMON_CFLAGS)
+chktime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/include/grub/datetime.h b/include/grub/datetime.h
new file mode 100755
index 0000000..b8f62b1
--- /dev/null
+++ b/include/grub/datetime.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_DATETIME_HEADER
+#define KERNEL_DATETIME_HEADER 1
+
+#include <grub/types.h>
+
+/* Return date and time. */
+grub_err_t grub_get_date (int *year, int *month, int *day);
+grub_err_t grub_get_time (int *hour, int *minute, int *second);
+
+#endif /* ! KERNEL_DATETIME_HEADER */
diff --git a/include/grub/i386/cmos.h b/include/grub/i386/cmos.h
new file mode 100755
index 0000000..4e3304c
--- /dev/null
+++ b/include/grub/i386/cmos.h
@@ -0,0 +1,61 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CPU_CMOS_H
+#define GRUB_CPU_CMOS_H 1
+
+#include <grub/types.h>
+#include <grub/i386/io.h>
+
+#define GRUB_CMOS_ADDR_REG 0x70
+#define GRUB_CMOS_DATA_REG 0x71
+
+#define GRUB_CMOS_INDEX_SECONDS 0
+#define GRUB_CMOS_INDEX_SECOND_ALARM 1
+#define GRUB_CMOS_INDEX_MINUTES 2
+#define GRUB_CMOS_INDEX_MINUTE_ALARM 3
+#define GRUB_CMOS_INDEX_HOURS 4
+#define GRUB_CMOS_INDEX_HOUR_ALARM 5
+#define GRUB_CMOS_INDEX_DAY_OF_WEEK 6
+#define GRUB_CMOS_INDEX_DAY_OF_MONTH 7
+#define GRUB_CMOS_INDEX_MONTH 8
+#define GRUB_CMOS_INDEX_YEAR 9
+
+#define GRUB_CMOS_INDEX_STATUS_A 0xA
+#define GRUB_CMOS_INDEX_STATUS_B 0xB
+#define GRUB_CMOS_INDEX_STATUS_C 0xC
+#define GRUB_CMOS_INDEX_STATUS_D 0xD
+
+#define GRUB_CMOS_STATUS_B_DAYLIGHT 1
+#define GRUB_CMOS_STATUS_B_24HOUR 2
+#define GRUB_CMOS_STATUS_B_BINARY 4
+
+static inline grub_uint8_t
+grub_bcd_to_num (grub_uint8_t a)
+{
+ return ((a >> 4) * 10 + (a & 0xF));
+}
+
+static inline grub_uint8_t
+grub_cmos_read (grub_uint8_t index)
+{
+ grub_outb (index, GRUB_CMOS_ADDR_REG);
+ return grub_inb (GRUB_CMOS_DATA_REG);
+}
+
+#endif /* GRUB_CPU_PCI_H */
diff --git a/kern/i386/datetime.c b/kern/i386/datetime.c
new file mode 100755
index 0000000..4170cab
--- /dev/null
+++ b/kern/i386/datetime.c
@@ -0,0 +1,118 @@
+/* kern/i386/datetime.c - x86 CMOS datetime access function.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/time.h>
+#include <grub/misc.h>
+#include <grub/datetime.h>
+#include <grub/i386/cmos.h>
+
+grub_err_t
+grub_get_date (int *year, int *month, int *day)
+{
+ int is_bcd;
+ grub_uint8_t value;
+
+ is_bcd = ! (grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B) &
+ GRUB_CMOS_STATUS_B_BINARY);
+
+ if (year)
+ {
+ value = grub_cmos_read (GRUB_CMOS_INDEX_YEAR);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ *year = value;
+ *year += (value < 80) ? 2000 : 1900;
+ }
+
+ if (month)
+ {
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ *month = value;
+ }
+
+ if (day)
+ {
+ value = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ *day = value;
+ }
+
+ return 0;
+}
+
+grub_err_t
+grub_get_time (int *hour, int *minute, int *second)
+{
+ int is_bcd;
+ grub_uint8_t value;
+
+ is_bcd = ! (grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B) &
+ GRUB_CMOS_STATUS_B_BINARY);
+
+
+ if (hour)
+ {
+ int is_12hour;
+
+ is_12hour = ! (grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B) &
+ GRUB_CMOS_STATUS_B_24HOUR);
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_HOURS);
+ if (is_12hour)
+ {
+ is_12hour = (value & 0x80);
+ value &= 0x7F;
+ }
+
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ if (is_12hour)
+ value += 12;
+
+ *hour = value;
+ }
+
+ if (minute)
+ {
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MINUTES);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ *minute = value;
+ }
+
+ if (second)
+ {
+ value = grub_cmos_read (GRUB_CMOS_INDEX_SECONDS);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ *second = value;
+ }
+
+ return 0;
+}
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-06 15:09 ` Bean
@ 2008-08-06 19:57 ` Robert Millan
2008-08-07 8:05 ` Bean
0 siblings, 1 reply; 28+ messages in thread
From: Robert Millan @ 2008-08-06 19:57 UTC (permalink / raw)
To: The development of GRUB 2
On Wed, Aug 06, 2008 at 11:09:44PM +0800, Bean wrote:
> On Wed, Aug 6, 2008 at 7:35 PM, Robert Millan <rmh@aybabtu.com> wrote:
> > Can we make this portable by accessing 0x70 / 0x71 I/O ports instead?
>
> Hi,
>
> Good point. The new patch uses cmos to get datetime setting, it should
> be generic among i386 platforms.
Yep, this works on Coreboot as well (with the obvious i386-coreboot.rmk
adjustment). Nice work!
> + grub_printf ("%d-%02d-%02d %02d:%02d:%02d %d\n",
> + year, month, day, hour, min, sec, dow);
Btw, the dow part looks weird when printed. Without looking at the code,
it's difficult to tell what that final number means.
--
Robert Millan
The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
how) you may access your data; but nobody's threatening your freedom: we
still allow you to remove your data and not access it at all."
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-06 19:57 ` Robert Millan
@ 2008-08-07 8:05 ` Bean
2008-08-07 10:21 ` Robert Millan
0 siblings, 1 reply; 28+ messages in thread
From: Bean @ 2008-08-07 8:05 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 1921 bytes --]
On Thu, Aug 7, 2008 at 3:57 AM, Robert Millan <rmh@aybabtu.com> wrote:
> On Wed, Aug 06, 2008 at 11:09:44PM +0800, Bean wrote:
>> On Wed, Aug 6, 2008 at 7:35 PM, Robert Millan <rmh@aybabtu.com> wrote:
>> > Can we make this portable by accessing 0x70 / 0x71 I/O ports instead?
>>
>> Hi,
>>
>> Good point. The new patch uses cmos to get datetime setting, it should
>> be generic among i386 platforms.
>
> Yep, this works on Coreboot as well (with the obvious i386-coreboot.rmk
> adjustment). Nice work!
>
>> + grub_printf ("%d-%02d-%02d %02d:%02d:%02d %d\n",
>> + year, month, day, hour, min, sec, dow);
>
> Btw, the dow part looks weird when printed. Without looking at the code,
> it's difficult to tell what that final number means.
Hi,
This patch replaces the day of week number with string. Also, it
extends to efi and other i386 platform as well.
2008-08-07 Bean <bean123ch@gmail.com>
* conf/i386-pc.rmk (pkglib_MODULES): Add chktime.mod.
(chktime_mod_SOURCES): New macro.
(chktime_mod_CFLAGS): Likewise.
(chktime_mod_LDFLAGS): Likewise.
* conf/i386-coreboot.rmk (pkglib_MODULES): Add chktime.mod.
(chktime_mod_SOURCES): New macro.
(chktime_mod_CFLAGS): Likewise.
(chktime_mod_LDFLAGS): Likewise.
* conf/i386-ieee1275.rmk (pkglib_MODULES): Add chktime.mod.
(chktime_mod_SOURCES): New macro.
(chktime_mod_CFLAGS): Likewise.
(chktime_mod_LDFLAGS): Likewise.
* conf/i386-efi.rmk (pkglib_MODULES): Add chktime.mod.
(chktime_mod_SOURCES): New macro.
(chktime_mod_CFLAGS): Likewise.
(chktime_mod_LDFLAGS): Likewise.
* conf/x86_64-efi.rmk (pkglib_MODULES): Add chktime.mod.
(chktime_mod_SOURCES): New macro.
(chktime_mod_CFLAGS): Likewise.
(chktime_mod_LDFLAGS): Likewise.
* commands/checktime.c: New file.
* include/grub/datetime.h: Likewise.
* include/grub/i386/cmos.h: Likewise.
* kern/i386/datetime.c: Likewise.
* kern/efi/datetime.c: Likewise.
--
Bean
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: checktime_3.diff --]
[-- Type: text/x-diff; name=checktime_3.diff, Size: 15690 bytes --]
diff --git a/commands/checktime.c b/commands/checktime.c
new file mode 100644
index 0000000..1cbd8f0
--- /dev/null
+++ b/commands/checktime.c
@@ -0,0 +1,150 @@
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/datetime.h>
+
+static int
+get_day_of_week (struct grub_datetime *datetime)
+{
+ int a, y, m;
+
+ a = (14 - datetime->month) / 12;
+ y = datetime->year - a;
+ m = datetime->month + 12 * a - 2;
+
+ return (datetime->day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7;
+}
+
+static grub_err_t
+grub_cmd_checktime (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_datetime datetime;
+ int dow, i;
+ int limit[5][2] = {{0, 59}, {0, 23}, {1, 31}, {1, 12}, {0, 7}};
+ int field[5];
+ char* dow_names[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+
+ if (grub_get_datetime (&datetime))
+ return grub_errno;
+
+ dow = get_day_of_week (&datetime);
+
+ field[0] = datetime.minute;
+ field[1] = datetime.hour;
+ field[2] = datetime.day;
+ field[3] = datetime.month;
+ field[4] = dow;
+
+ if (argc == 0)
+ {
+ grub_printf ("%d-%02d-%02d %02d:%02d:%02d %s\n",
+ datetime.year, datetime.month, datetime.day,
+ datetime.hour, datetime.minute, datetime.second,
+ dow_names[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-coreboot.rmk b/conf/i386-coreboot.rmk
index 5aee1f8..f377057 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -100,7 +100,7 @@ pkglib_MODULES = _linux.mod linux.mod normal.mod \
_multiboot.mod multiboot.mod aout.mod \
play.mod cpuid.mod serial.mod ata.mod \
memdisk.mod pci.mod lspci.mod reboot.mod \
- halt.mod
+ halt.mod chktime.mod
# For _linux.mod.
_linux_mod_SOURCES = loader/i386/pc/linux.c
@@ -185,4 +185,9 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For chktime.mod
+chktime_mod_SOURCES = commands/checktime.c kern/i386/datetime.c
+chktime_mod_CFLAGS = $(COMMON_CFLAGS)
+chktime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index a3234b5..8241462 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -75,7 +75,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
- _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod
+ _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod \
+ chktime.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -166,4 +167,9 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For chktime.mod
+chktime_mod_SOURCES = commands/checktime.c kern/efi/datetime.c
+chktime_mod_CFLAGS = $(COMMON_CFLAGS)
+chktime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index 818dc91..63fab0e 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -103,7 +106,7 @@ grub_install_SOURCES = util/ieee1275/grub-install.in
# Modules.
pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod cpuid.mod \
multiboot.mod _multiboot.mod aout.mod serial.mod linux.mod \
- _linux.mod nand.mod memdisk.mod pci.mod lspci.mod
+ _linux.mod nand.mod memdisk.mod pci.mod lspci.mod chktime.mod
# For normal.mod.
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
@@ -187,4 +190,9 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For chktime.mod
+chktime_mod_SOURCES = commands/checktime.c kern/i386/datetime.c
+chktime_mod_CFLAGS = $(COMMON_CFLAGS)
+chktime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index c1e4ac4..f383160 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -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/checktime.c kern/i386/datetime.c
+chktime_mod_CFLAGS = $(COMMON_CFLAGS)
+chktime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
index 25dc8eb..899d0ea 100644
--- a/conf/x86_64-efi.rmk
+++ b/conf/x86_64-efi.rmk
@@ -77,7 +77,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
- cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod
+ cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod \
+ chktime.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -167,4 +170,9 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For chktime.mod
+chktime_mod_SOURCES = commands/checktime.c kern/efi/datetime.c
+chktime_mod_CFLAGS = $(COMMON_CFLAGS)
+chktime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/include/grub/datetime.h b/include/grub/datetime.h
new file mode 100644
index 0000000..114cac9
--- /dev/null
+++ b/include/grub/datetime.h
@@ -0,0 +1,38 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_DATETIME_HEADER
+#define KERNEL_DATETIME_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+
+struct grub_datetime
+{
+ grub_uint16_t year;
+ grub_uint8_t month;
+ grub_uint8_t day;
+ grub_uint8_t hour;
+ grub_uint8_t minute;
+ grub_uint8_t second;
+};
+
+/* Return date and time. */
+grub_err_t grub_get_datetime (struct grub_datetime *datetime);
+
+#endif /* ! KERNEL_DATETIME_HEADER */
diff --git a/include/grub/i386/cmos.h b/include/grub/i386/cmos.h
new file mode 100644
index 0000000..bc60ad0
--- /dev/null
+++ b/include/grub/i386/cmos.h
@@ -0,0 +1,61 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CPU_CMOS_H
+#define GRUB_CPU_CMOS_H 1
+
+#include <grub/types.h>
+#include <grub/i386/io.h>
+
+#define GRUB_CMOS_ADDR_REG 0x70
+#define GRUB_CMOS_DATA_REG 0x71
+
+#define GRUB_CMOS_INDEX_SECOND 0
+#define GRUB_CMOS_INDEX_SECOND_ALARM 1
+#define GRUB_CMOS_INDEX_MINUTE 2
+#define GRUB_CMOS_INDEX_MINUTE_ALARM 3
+#define GRUB_CMOS_INDEX_HOUR 4
+#define GRUB_CMOS_INDEX_HOUR_ALARM 5
+#define GRUB_CMOS_INDEX_DAY_OF_WEEK 6
+#define GRUB_CMOS_INDEX_DAY_OF_MONTH 7
+#define GRUB_CMOS_INDEX_MONTH 8
+#define GRUB_CMOS_INDEX_YEAR 9
+
+#define GRUB_CMOS_INDEX_STATUS_A 0xA
+#define GRUB_CMOS_INDEX_STATUS_B 0xB
+#define GRUB_CMOS_INDEX_STATUS_C 0xC
+#define GRUB_CMOS_INDEX_STATUS_D 0xD
+
+#define GRUB_CMOS_STATUS_B_DAYLIGHT 1
+#define GRUB_CMOS_STATUS_B_24HOUR 2
+#define GRUB_CMOS_STATUS_B_BINARY 4
+
+static inline grub_uint8_t
+grub_bcd_to_num (grub_uint8_t a)
+{
+ return ((a >> 4) * 10 + (a & 0xF));
+}
+
+static inline grub_uint8_t
+grub_cmos_read (grub_uint8_t index)
+{
+ grub_outb (index, GRUB_CMOS_ADDR_REG);
+ return grub_inb (GRUB_CMOS_DATA_REG);
+}
+
+#endif /* GRUB_CPU_PCI_H */
diff --git a/kern/efi/datetime.c b/kern/efi/datetime.c
new file mode 100644
index 0000000..03026a2
--- /dev/null
+++ b/kern/efi/datetime.c
@@ -0,0 +1,48 @@
+/* kern/efi/datetime.c - efi datetime function.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/datetime.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+ grub_efi_status_t status;
+ struct grub_efi_time efi_time;
+
+ status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
+ &efi_time, 0);
+
+ if (status)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t get datetime");
+ else
+ {
+ datetime->year = efi_time.year;
+ datetime->month = efi_time.month;
+ datetime->day = efi_time.day;
+ datetime->hour = efi_time.hour;
+ datetime->minute = efi_time.minute;
+ datetime->second = efi_time.second;
+ }
+
+ return 0;
+}
diff --git a/kern/i386/datetime.c b/kern/i386/datetime.c
new file mode 100644
index 0000000..481920a
--- /dev/null
+++ b/kern/i386/datetime.c
@@ -0,0 +1,82 @@
+/* kern/i386/datetime.c - x86 CMOS datetime function.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/datetime.h>
+#include <grub/i386/cmos.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+ int is_bcd, is_12hour;;
+ grub_uint8_t value, flag;
+
+ flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+
+ is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_YEAR);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->year = value;
+ datetime->year += (value < 80) ? 2000 : 1900;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->month = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->day = value;
+
+ is_12hour = ! (flag & GRUB_CMOS_STATUS_B_24HOUR);
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_HOUR);
+ if (is_12hour)
+ {
+ is_12hour = (value & 0x80);
+ value &= 0x7F;
+ }
+
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ if (is_12hour)
+ value += 12;
+
+ datetime->hour = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->minute = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_SECOND);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->second = value;
+
+ return 0;
+}
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-07 8:05 ` Bean
@ 2008-08-07 10:21 ` Robert Millan
2008-08-07 11:19 ` Bean
0 siblings, 1 reply; 28+ messages in thread
From: Robert Millan @ 2008-08-07 10:21 UTC (permalink / raw)
To: The development of GRUB 2
On Thu, Aug 07, 2008 at 04:05:04PM +0800, Bean wrote:
> * conf/i386-ieee1275.rmk (pkglib_MODULES): Add chktime.mod.
> (chktime_mod_SOURCES): New macro.
> (chktime_mod_CFLAGS): Likewise.
> (chktime_mod_LDFLAGS): Likewise.
Uhm I'm not sure those have a PC-compatible CMOS ...
--
Robert Millan
The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
how) you may access your data; but nobody's threatening your freedom: we
still allow you to remove your data and not access it at all."
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-07 10:21 ` Robert Millan
@ 2008-08-07 11:19 ` Bean
2008-08-07 17:52 ` Bean
0 siblings, 1 reply; 28+ messages in thread
From: Bean @ 2008-08-07 11:19 UTC (permalink / raw)
To: The development of GRUB 2
On Thu, Aug 7, 2008 at 6:21 PM, Robert Millan <rmh@aybabtu.com> wrote:
> On Thu, Aug 07, 2008 at 04:05:04PM +0800, Bean wrote:
>> * conf/i386-ieee1275.rmk (pkglib_MODULES): Add chktime.mod.
>> (chktime_mod_SOURCES): New macro.
>> (chktime_mod_CFLAGS): Likewise.
>> (chktime_mod_LDFLAGS): Likewise.
>
> Uhm I'm not sure those have a PC-compatible CMOS ...
Hi,
Yes, I try it with olpc, it works.
--
Bean
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-07 11:19 ` Bean
@ 2008-08-07 17:52 ` Bean
2008-08-07 18:17 ` Colin D Bennett
2008-08-07 19:06 ` Robert Millan
0 siblings, 2 replies; 28+ messages in thread
From: Bean @ 2008-08-07 17:52 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 3210 bytes --]
On Thu, Aug 7, 2008 at 7:19 PM, Bean <bean123ch@gmail.com> wrote:
> On Thu, Aug 7, 2008 at 6:21 PM, Robert Millan <rmh@aybabtu.com> wrote:
>> On Thu, Aug 07, 2008 at 04:05:04PM +0800, Bean wrote:
>>> * conf/i386-ieee1275.rmk (pkglib_MODULES): Add chktime.mod.
>>> (chktime_mod_SOURCES): New macro.
>>> (chktime_mod_CFLAGS): Likewise.
>>> (chktime_mod_LDFLAGS): Likewise.
>>
>> Uhm I'm not sure those have a PC-compatible CMOS ...
>
> Hi,
>
> Yes, I try it with olpc, it works.
Hi,
I have seperated the commands as nyu suggests in the IRC.
1. date [MMDDhhmm[[CC]YY][.ss]]
Set/Display current datetime, to set date, The format is the same as
the date command, you can also use - or : to seperate the numbers. For
example:
date 0902
Sep, 2.
date 10-05-13-15
Oct 5, 13:15
2. crontab min hour day_of_month month day_of_week
It's the same as the previous checktime command, except that it
doesn't display the current date when no parameter is provided.
2008-08-07 Bean <bean123ch@gmail.com>
* conf/i386-pc.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and crontab.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(crontab_mod_SOURCES): Likewise.
(crontab_mod_CFLAGS): Likewise.
(crontab_mod_LDFLAGS): Likewise.
* conf/i386-coreboot.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and crontab.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(crontab_mod_SOURCES): Likewise.
(crontab_mod_CFLAGS): Likewise.
(crontab_mod_LDFLAGS): Likewise.
* conf/i386-ieee1275.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and crontab.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(crontab_mod_SOURCES): Likewise.
(crontab_mod_CFLAGS): Likewise.
(crontab_mod_LDFLAGS): Likewise.
* conf/i386-efi.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and crontab.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(crontab_mod_SOURCES): Likewise.
(crontab_mod_CFLAGS): Likewise.
(crontab_mod_LDFLAGS): Likewise.
* conf/x86_64-efi.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and crontab.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(crontab_mod_SOURCES): Likewise.
(crontab_mod_CFLAGS): Likewise.
(crontab_mod_LDFLAGS): Likewise.
* commands/date.c: New file.
* commands/crontab.c: Likewise.
* include/grub/datetime.h: Likewise.
* include/grub/i386/cmos.h: Likewise.
* kern/generic/get_dow.c: Likewise.
* kern/i386/datetime.c: Likewise.
* kern/efi/datetime.c: Likewise.
--
Bean
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: date.diff --]
[-- Type: text/x-diff; name=date.diff, Size: 26070 bytes --]
diff --git a/commands/crontab.c b/commands/crontab.c
new file mode 100644
index 0000000..b646842
--- /dev/null
+++ b/commands/crontab.c
@@ -0,0 +1,127 @@
+/* crontab.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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/datetime.h>
+
+static grub_err_t
+grub_cmd_crontab (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_datetime datetime;
+ int dow, i;
+ int limit[5][2] = {{0, 59}, {0, 23}, {1, 31}, {1, 12}, {0, 7}};
+ int field[5];
+
+ if (grub_get_datetime (&datetime))
+ return grub_errno;
+
+ dow = grub_get_day_of_week (&datetime);
+
+ field[0] = datetime.minute;
+ field[1] = datetime.hour;
+ field[2] = datetime.day;
+ field[3] = datetime.month;
+ field[4] = dow;
+
+ 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(crontab)
+{
+ (void) mod; /* To stop warning. */
+ grub_register_command ("crontab", grub_cmd_crontab,
+ GRUB_COMMAND_FLAG_BOTH,
+ "crontab min hour day_of_month month day_of_week",
+ "Command to test current date/time.", 0);
+}
+
+GRUB_MOD_FINI(crontab)
+{
+ grub_unregister_command ("crontab");
+}
diff --git a/commands/date.c b/commands/date.c
new file mode 100644
index 0000000..ec50c45
--- /dev/null
+++ b/commands/date.c
@@ -0,0 +1,161 @@
+/* date.c - command to set/get 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/datetime.h>
+
+static int
+get_bcd (char **str)
+{
+ int res, i;
+
+ res = 0;
+ for (i = 0; i < 2; i++)
+ {
+ if ((**str >= '0') && (**str <= '9'))
+ res = res * 10 + (**str - '0');
+ else
+ return -1;
+
+ (*str)++;
+ }
+
+ return res;
+}
+
+static grub_err_t
+grub_cmd_date (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_datetime datetime;
+ char* dow_names[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+ int pos, mask;
+ char *p;
+
+ if (argc == 0)
+ {
+ if (grub_get_datetime (&datetime))
+ return grub_errno;
+
+ grub_printf ("%d-%02d-%02d %02d:%02d:%02d %s\n",
+ datetime.year, datetime.month, datetime.day,
+ datetime.hour, datetime.minute, datetime.second,
+ dow_names[grub_get_day_of_week (&datetime)]);
+
+ return 0;
+ }
+
+ p = args[0];
+ mask = 0;
+
+ for (pos = 0; (*p); pos++)
+ {
+ int n;
+
+ n = get_bcd (&p);
+ if (n < 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
+
+ switch (pos)
+ {
+ case 0:
+ if ((n < 1) || (n > 12))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
+
+ mask |= GRUB_DATETIME_SET_MONTH;
+ datetime.month = n;
+ break;
+
+ case 1:
+ if ((n < 1) || (n > 31))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
+
+ mask |= GRUB_DATETIME_SET_DAY;
+ datetime.day = n;
+ break;
+
+ case 2:
+ if (n > 23)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
+
+ mask |= GRUB_DATETIME_SET_HOUR;
+ datetime.hour = n;
+ break;
+
+ case 3:
+ if (n > 59)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
+
+ mask |= GRUB_DATETIME_SET_MINUTE;
+ datetime.minute = n;
+ break;
+
+ case 4:
+ if (n > 99)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
+
+ mask |= GRUB_DATETIME_SET_YEAR;
+ datetime.year = n;
+ if ((*p >= '0') && (*p <= '9'))
+ {
+ n = get_bcd (&p);
+ if ((n < 0) || (n > 99))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
+
+ datetime.year = datetime.year * 100 + n;
+ }
+ else
+ datetime.year += (datetime.year >= 80) ? 1900 : 2000;
+
+ if (*p == '.')
+ p++;
+ else if (*p != 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
+
+ break;
+
+ case 5:
+ mask |= GRUB_DATETIME_SET_SECOND;
+ datetime.second = n;
+ }
+
+ if ((*p == '-') || (*p == ':'))
+ p++;
+ }
+
+ return grub_set_datetime (&datetime, mask);
+}
+
+GRUB_MOD_INIT(checktime)
+{
+ (void) mod; /* To stop warning. */
+ grub_register_command ("date", grub_cmd_date,
+ GRUB_COMMAND_FLAG_BOTH,
+ "date [MMDDhhmm[[CC]YY][.ss]]",
+ "Command to get/set current date/time.", 0);
+}
+
+GRUB_MOD_FINI(checktime)
+{
+ grub_unregister_command ("date");
+}
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index 4827c0f..f2d5875 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -101,7 +101,7 @@ pkglib_MODULES = _linux.mod linux.mod normal.mod \
_multiboot.mod multiboot.mod aout.mod \
play.mod cpuid.mod serial.mod ata.mod \
memdisk.mod pci.mod lspci.mod reboot.mod \
- halt.mod
+ halt.mod datetime.mod date.mod crontab.mod
# For _linux.mod.
_linux_mod_SOURCES = loader/i386/pc/linux.c
@@ -186,4 +186,19 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = kern/i386/datetime.c kern/generic/get_dow.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For crontab.mod
+crontab_mod_SOURCES = commands/crontab.c
+crontab_mod_CFLAGS = $(COMMON_CFLAGS)
+crontab_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 2ce21b1..a7a2483 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -75,7 +75,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
- _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod
+ _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod \
+ datetime.mod date.mod crontab.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -167,4 +168,19 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = kern/efi/datetime.c kern/generic/get_dow.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For crontab.mod
+crontab_mod_SOURCES = commands/crontab.c
+crontab_mod_CFLAGS = $(COMMON_CFLAGS)
+crontab_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index a93845e..e6dc4bc 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -104,7 +104,8 @@ grub_install_SOURCES = util/ieee1275/grub-install.in
# Modules.
pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod cpuid.mod \
multiboot.mod _multiboot.mod aout.mod serial.mod linux.mod \
- _linux.mod nand.mod memdisk.mod pci.mod lspci.mod
+ _linux.mod nand.mod memdisk.mod pci.mod lspci.mod datetime.mod \
+ date.mod crontab.mod
# For normal.mod.
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
@@ -188,4 +189,19 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = kern/i386/datetime.c kern/generic/get_dow.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For crontab.mod
+crontab_mod_SOURCES = commands/crontab.c
+crontab_mod_CFLAGS = $(COMMON_CFLAGS)
+crontab_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index c1e4ac4..aa19219 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -163,7 +163,8 @@ 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 datetime.mod date.mod \
+ crontab.mod
# For biosdisk.mod.
biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -340,4 +341,19 @@ pxecmd_mod_SOURCES = commands/i386/pc/pxecmd.c
pxecmd_mod_CFLAGS = $(COMMON_CFLAGS)
pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = kern/i386/datetime.c kern/generic/get_dow.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For crontab.mod
+crontab_mod_SOURCES = commands/crontab.c
+crontab_mod_CFLAGS = $(COMMON_CFLAGS)
+crontab_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
index 25dc8eb..d911b31 100644
--- a/conf/x86_64-efi.rmk
+++ b/conf/x86_64-efi.rmk
@@ -77,7 +77,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
- cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod
+ cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod \
+ datetime.mod date.mod crontab.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -167,4 +168,19 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = kern/efi/datetime.c kern/generic/get_dow.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For crontab.mod
+crontab_mod_SOURCES = commands/crontab.c
+crontab_mod_CFLAGS = $(COMMON_CFLAGS)
+crontab_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/include/grub/datetime.h b/include/grub/datetime.h
new file mode 100644
index 0000000..b8c9f7e
--- /dev/null
+++ b/include/grub/datetime.h
@@ -0,0 +1,57 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_DATETIME_HEADER
+#define KERNEL_DATETIME_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+
+#define GRUB_DATETIME_SET_YEAR 1
+#define GRUB_DATETIME_SET_MONTH 2
+#define GRUB_DATETIME_SET_DAY 4
+#define GRUB_DATETIME_SET_DATE (GRUB_DATETIME_SET_YEAR | \
+ GRUB_DATETIME_SET_MONTH | \
+ GRUB_DATETIME_SET_DAY)
+
+#define GRUB_DATETIME_SET_HOUR 8
+#define GRUB_DATETIME_SET_MINUTE 16
+#define GRUB_DATETIME_SET_SECOND 32
+#define GRUB_DATETIME_SET_TIME (GRUB_DATETIME_SET_HOUR | \
+ GRUB_DATETIME_SET_MINUTE | \
+ GRUB_DATETIME_SET_SECOND)
+
+struct grub_datetime
+{
+ grub_uint16_t year;
+ grub_uint8_t month;
+ grub_uint8_t day;
+ grub_uint8_t hour;
+ grub_uint8_t minute;
+ grub_uint8_t second;
+};
+
+/* Return date and time. */
+grub_err_t grub_get_datetime (struct grub_datetime *datetime);
+
+/* Set date and time. */
+grub_err_t grub_set_datetime (struct grub_datetime *datetime, int mask);
+
+int grub_get_day_of_week (struct grub_datetime *datetime);
+
+#endif /* ! KERNEL_DATETIME_HEADER */
diff --git a/include/grub/i386/cmos.h b/include/grub/i386/cmos.h
new file mode 100644
index 0000000..d482a7d
--- /dev/null
+++ b/include/grub/i386/cmos.h
@@ -0,0 +1,74 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CPU_CMOS_H
+#define GRUB_CPU_CMOS_H 1
+
+#include <grub/types.h>
+#include <grub/i386/io.h>
+
+#define GRUB_CMOS_ADDR_REG 0x70
+#define GRUB_CMOS_DATA_REG 0x71
+
+#define GRUB_CMOS_INDEX_SECOND 0
+#define GRUB_CMOS_INDEX_SECOND_ALARM 1
+#define GRUB_CMOS_INDEX_MINUTE 2
+#define GRUB_CMOS_INDEX_MINUTE_ALARM 3
+#define GRUB_CMOS_INDEX_HOUR 4
+#define GRUB_CMOS_INDEX_HOUR_ALARM 5
+#define GRUB_CMOS_INDEX_DAY_OF_WEEK 6
+#define GRUB_CMOS_INDEX_DAY_OF_MONTH 7
+#define GRUB_CMOS_INDEX_MONTH 8
+#define GRUB_CMOS_INDEX_YEAR 9
+
+#define GRUB_CMOS_INDEX_STATUS_A 0xA
+#define GRUB_CMOS_INDEX_STATUS_B 0xB
+#define GRUB_CMOS_INDEX_STATUS_C 0xC
+#define GRUB_CMOS_INDEX_STATUS_D 0xD
+
+#define GRUB_CMOS_STATUS_B_DAYLIGHT 1
+#define GRUB_CMOS_STATUS_B_24HOUR 2
+#define GRUB_CMOS_STATUS_B_BINARY 4
+
+static inline grub_uint8_t
+grub_bcd_to_num (grub_uint8_t a)
+{
+ return ((a >> 4) * 10 + (a & 0xF));
+}
+
+static inline grub_uint8_t
+grub_num_to_bcd (grub_uint8_t a)
+{
+ return (((a / 10) << 4) + (a % 10));
+}
+
+static inline grub_uint8_t
+grub_cmos_read (grub_uint8_t index)
+{
+ grub_outb (index, GRUB_CMOS_ADDR_REG);
+ return grub_inb (GRUB_CMOS_DATA_REG);
+}
+
+static inline void
+grub_cmos_write (grub_uint8_t index, grub_uint8_t value)
+{
+ grub_outb (index, GRUB_CMOS_ADDR_REG);
+ grub_outb (value, GRUB_CMOS_DATA_REG);
+}
+
+#endif /* GRUB_CPU_PCI_H */
diff --git a/kern/efi/datetime.c b/kern/efi/datetime.c
new file mode 100644
index 0000000..4ba38be
--- /dev/null
+++ b/kern/efi/datetime.c
@@ -0,0 +1,87 @@
+/* kern/efi/datetime.c - efi datetime function.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/datetime.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+ grub_efi_status_t status;
+ struct grub_efi_time efi_time;
+
+ status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
+ &efi_time, 0);
+
+ if (status)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t get datetime");
+ else
+ {
+ datetime->year = efi_time.year;
+ datetime->month = efi_time.month;
+ datetime->day = efi_time.day;
+ datetime->hour = efi_time.hour;
+ datetime->minute = efi_time.minute;
+ datetime->second = efi_time.second;
+ }
+
+ return 0;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime, int mask)
+{
+ grub_efi_status_t status;
+ struct grub_efi_time efi_time;
+
+ status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
+ &efi_time, 0);
+
+ if (status)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t get datetime");
+
+ if (mask & GRUB_DATETIME_SET_YEAR)
+ efi_time.year = datetime->year;
+
+ if (mask & GRUB_DATETIME_SET_MONTH)
+ efi_time.month = datetime->month;
+
+ if (mask & GRUB_DATETIME_SET_DAY)
+ efi_time.day = datetime->day;
+
+ if (mask & GRUB_DATETIME_SET_HOUR)
+ efi_time.hour = datetime->hour;
+
+ if (mask & GRUB_DATETIME_SET_MINUTE)
+ efi_time.minute = datetime->minute;
+
+ if (mask & GRUB_DATETIME_SET_SECOND)
+ efi_time.second = datetime->second;
+
+ status = efi_call_1 (grub_efi_system_table->runtime_services->set_time,
+ &efi_time);
+
+ if (status)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t set datetime");
+
+ return 0;
+}
diff --git a/kern/generic/get_dow.c b/kern/generic/get_dow.c
new file mode 100755
index 0000000..fd1a032
--- /dev/null
+++ b/kern/generic/get_dow.c
@@ -0,0 +1,32 @@
+/* get_dow - Calculate the day of week. */
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/datetime.h>
+
+int
+grub_get_day_of_week (struct grub_datetime *datetime)
+{
+ int a, y, m;
+
+ a = (14 - datetime->month) / 12;
+ y = datetime->year - a;
+ m = datetime->month + 12 * a - 2;
+
+ return (datetime->day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7;
+}
diff --git a/kern/i386/datetime.c b/kern/i386/datetime.c
new file mode 100644
index 0000000..466a404
--- /dev/null
+++ b/kern/i386/datetime.c
@@ -0,0 +1,175 @@
+/* kern/i386/datetime.c - x86 CMOS datetime function.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/datetime.h>
+#include <grub/i386/cmos.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+ int is_bcd, is_12hour;
+ grub_uint8_t value, flag;
+
+ flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+
+ is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_YEAR);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->year = value;
+ datetime->year += (value < 80) ? 2000 : 1900;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->month = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->day = value;
+
+ is_12hour = ! (flag & GRUB_CMOS_STATUS_B_24HOUR);
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_HOUR);
+ if (is_12hour)
+ {
+ is_12hour = (value & 0x80);
+
+ value &= 0x7F;
+ value--;
+ }
+
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ if (is_12hour)
+ value += 12;
+
+ datetime->hour = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->minute = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_SECOND);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->second = value;
+
+ return 0;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime, int mask)
+{
+ int is_bcd;
+ grub_uint8_t value, flag;
+
+ flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+
+ is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
+
+ if (mask & GRUB_DATETIME_SET_YEAR)
+ {
+ value = ((datetime->year >= 2000) ? datetime->year - 2000 :
+ datetime->year - 1900);
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_MONTH)
+ {
+ value = datetime->month;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_DAY)
+ {
+ value = datetime->day;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_HOUR)
+ {
+ int is_12hour;
+
+ value = datetime->hour;
+
+ is_12hour = (! (flag & GRUB_CMOS_STATUS_B_24HOUR));
+
+ if (is_12hour)
+ {
+ value++;
+
+ if (value > 12)
+ value -= 12;
+ else
+ is_12hour = 0;
+ }
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ if (is_12hour)
+ value |= 0x80;
+
+ grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_MINUTE)
+ {
+ value = datetime->minute;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_SECOND)
+ {
+ value = datetime->second;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value);
+ }
+
+ return 0;
+}
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-07 17:52 ` Bean
@ 2008-08-07 18:17 ` Colin D Bennett
2008-08-07 19:12 ` Robert Millan
2008-08-07 19:06 ` Robert Millan
1 sibling, 1 reply; 28+ messages in thread
From: Colin D Bennett @ 2008-08-07 18:17 UTC (permalink / raw)
To: grub-devel
I just have a couple of suggestions:
On Fri, 8 Aug 2008 01:52:07 +0800
Bean <bean123ch@gmail.com> wrote:
> On Thu, Aug 7, 2008 at 7:19 PM, Bean <bean123ch@gmail.com> wrote:
> 1. date [MMDDhhmm[[CC]YY][.ss]]
>
> Set/Display current datetime, to set date, The format is the same as
> the date command, you can also use - or : to seperate the numbers. For
> example:
>
> date 0902
> Sep, 2.
>
> date 10-05-13-15
> Oct 5, 13:15
I know the reason for using that format is to be compatible with the
Unix 'date' command, but I find it impossible to remember the arcane
format it accepts. Do you think it would be more straightforward to
accept the ISO standard date format (ISO 8601). For instance:
date 2008-10-05T13:15
(5 October 2008)
or, as syntactic sugar, let each argument be either a time or date:
date 2008-10-05 13:15
> 2. crontab min hour day_of_month month day_of_week
This really doesn't allow you to edit a crontab, does it? If not, is
there a more appropriate name we could use instead of 'crontab'?
Perhaps 'testdate' or something?
Regards,
Colin
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-07 17:52 ` Bean
2008-08-07 18:17 ` Colin D Bennett
@ 2008-08-07 19:06 ` Robert Millan
1 sibling, 0 replies; 28+ messages in thread
From: Robert Millan @ 2008-08-07 19:06 UTC (permalink / raw)
To: The development of GRUB 2
On Fri, Aug 08, 2008 at 01:52:07AM +0800, Bean wrote:
> date 10-05-13-15
> Oct 5, 13:15
Nice. Btw this will be real fun for translators when we have gettext
support ;-)
> + if (n < 0)
> + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
> +
> + switch (pos)
> + {
> + case 0:
> + if ((n < 1) || (n > 12))
> + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
> +
> + mask |= GRUB_DATETIME_SET_MONTH;
> + datetime.month = n;
> + break;
> +
> + case 1:
> + if ((n < 1) || (n > 31))
> + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
> +
> + mask |= GRUB_DATETIME_SET_DAY;
> + datetime.day = n;
> + break;
> +
> + case 2:
> + if (n > 23)
> + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
> +
> + mask |= GRUB_DATETIME_SET_HOUR;
> + datetime.hour = n;
> + break;
> +
> + case 3:
> + if (n > 59)
> + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
> +
> + mask |= GRUB_DATETIME_SET_MINUTE;
> + datetime.minute = n;
> + break;
> +
> + case 4:
> + if (n > 99)
> + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid date");
Since those grub_error calls are always the same, I think it'd be a good
idea to group them together in a "fail:" section to save space.
--
Robert Millan
The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
how) you may access your data; but nobody's threatening your freedom: we
still allow you to remove your data and not access it at all."
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-07 18:17 ` Colin D Bennett
@ 2008-08-07 19:12 ` Robert Millan
2008-08-09 4:34 ` Bean
0 siblings, 1 reply; 28+ messages in thread
From: Robert Millan @ 2008-08-07 19:12 UTC (permalink / raw)
To: The development of GRUB 2
On Thu, Aug 07, 2008 at 11:17:14AM -0700, Colin D Bennett wrote:
> I just have a couple of suggestions:
>
> On Fri, 8 Aug 2008 01:52:07 +0800
> Bean <bean123ch@gmail.com> wrote:
>
> > On Thu, Aug 7, 2008 at 7:19 PM, Bean <bean123ch@gmail.com> wrote:
> > 1. date [MMDDhhmm[[CC]YY][.ss]]
> >
> > Set/Display current datetime, to set date, The format is the same as
> > the date command, you can also use - or : to seperate the numbers. For
> > example:
> >
> > date 0902
> > Sep, 2.
> >
> > date 10-05-13-15
> > Oct 5, 13:15
>
> I know the reason for using that format is to be compatible with the
> Unix 'date' command, but I find it impossible to remember the arcane
> format it accepts.
We could have its --help include this "[MMDDhhmm[[CC]YY][.ss]]" boilerplate,
like with gnu date.
IMHO it's an advantage that the input for changing the date is defined
simple instead of accepting lots of different layouts. This means less code
size, less complexity and also makes the commands more usable in scripts and
such.
> > 2. crontab min hour day_of_month month day_of_week
>
> This really doesn't allow you to edit a crontab, does it? If not, is
> there a more appropriate name we could use instead of 'crontab'?
> Perhaps 'testdate' or something?
I think it's good that it mentions crontab, since it basicaly works with
that format, but I agree that it isn't consistent with the crontab command.
How about something that contains 'crontab' but isn't 'crontab'? Like
'test_crontab', 'crontab_check' or something like this?
--
Robert Millan
The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
how) you may access your data; but nobody's threatening your freedom: we
still allow you to remove your data and not access it at all."
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-07 19:12 ` Robert Millan
@ 2008-08-09 4:34 ` Bean
2008-08-09 11:20 ` Isaac Dupree
0 siblings, 1 reply; 28+ messages in thread
From: Bean @ 2008-08-09 4:34 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 4247 bytes --]
On Fri, Aug 8, 2008 at 3:12 AM, Robert Millan <rmh@aybabtu.com> wrote:
> On Thu, Aug 07, 2008 at 11:17:14AM -0700, Colin D Bennett wrote:
>> I just have a couple of suggestions:
>>
>> On Fri, 8 Aug 2008 01:52:07 +0800
>> Bean <bean123ch@gmail.com> wrote:
>>
>> > On Thu, Aug 7, 2008 at 7:19 PM, Bean <bean123ch@gmail.com> wrote:
>> > 1. date [MMDDhhmm[[CC]YY][.ss]]
>> >
>> > Set/Display current datetime, to set date, The format is the same as
>> > the date command, you can also use - or : to seperate the numbers. For
>> > example:
>> >
>> > date 0902
>> > Sep, 2.
>> >
>> > date 10-05-13-15
>> > Oct 5, 13:15
>>
>> I know the reason for using that format is to be compatible with the
>> Unix 'date' command, but I find it impossible to remember the arcane
>> format it accepts.
>
> We could have its --help include this "[MMDDhhmm[[CC]YY][.ss]]" boilerplate,
> like with gnu date.
>
> IMHO it's an advantage that the input for changing the date is defined
> simple instead of accepting lots of different layouts. This means less code
> size, less complexity and also makes the commands more usable in scripts and
> such.
>
I agree with Colin the datetime representation should be more
intuitive, but we should stick to one layout. I use the following
format now:
date [[year-]month-day] [hour:minute[:second]]
date is separated by `-' , and time `:', year and second part can be omitted.
>> > 2. crontab min hour day_of_month month day_of_week
>>
>> This really doesn't allow you to edit a crontab, does it? If not, is
>> there a more appropriate name we could use instead of 'crontab'?
>> Perhaps 'testdate' or something?
>
> I think it's good that it mentions crontab, since it basicaly works with
> that format, but I agree that it isn't consistent with the crontab command.
>
> How about something that contains 'crontab' but isn't 'crontab'? Like
> 'test_crontab', 'crontab_check' or something like this?
test_crontab looks good to me.
This is the new patch, if no one objects, I'd commit it soon.
2008-08-09 Bean <bean123ch@gmail.com>
* conf/i386-pc.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and crontab.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(crontab_mod_SOURCES): Likewise.
(crontab_mod_CFLAGS): Likewise.
(crontab_mod_LDFLAGS): Likewise.
* conf/i386-coreboot.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and crontab.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(crontab_mod_SOURCES): Likewise.
(crontab_mod_CFLAGS): Likewise.
(crontab_mod_LDFLAGS): Likewise.
* conf/i386-ieee1275.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and crontab.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(crontab_mod_SOURCES): Likewise.
(crontab_mod_CFLAGS): Likewise.
(crontab_mod_LDFLAGS): Likewise.
* conf/i386-efi.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and crontab.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(crontab_mod_SOURCES): Likewise.
(crontab_mod_CFLAGS): Likewise.
(crontab_mod_LDFLAGS): Likewise.
* conf/x86_64-efi.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and crontab.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(crontab_mod_SOURCES): Likewise.
(crontab_mod_CFLAGS): Likewise.
(crontab_mod_LDFLAGS): Likewise.
* commands/date.c: New file.
* commands/crontab.c: Likewise.
* include/grub/datetime.h: Likewise.
* include/grub/i386/cmos.h: Likewise.
* kern/generic/get_dow.c: Likewise.
* kern/i386/datetime.c: Likewise.
* kern/efi/datetime.c: Likewise.
--
Bean
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: date_2.diff --]
[-- Type: text/x-diff; name=date_2.diff, Size: 25261 bytes --]
diff --git a/commands/crontab.c b/commands/crontab.c
new file mode 100644
index 0000000..2a7b061
--- /dev/null
+++ b/commands/crontab.c
@@ -0,0 +1,127 @@
+/* crontab.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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/datetime.h>
+
+static grub_err_t
+grub_cmd_test_crontab (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_datetime datetime;
+ int dow, i;
+ int limit[5][2] = {{0, 59}, {0, 23}, {1, 31}, {1, 12}, {0, 7}};
+ int field[5];
+
+ if (grub_get_datetime (&datetime))
+ return grub_errno;
+
+ dow = grub_get_day_of_week (&datetime);
+
+ field[0] = datetime.minute;
+ field[1] = datetime.hour;
+ field[2] = datetime.day;
+ field[3] = datetime.month;
+ field[4] = dow;
+
+ 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(crontab)
+{
+ (void) mod; /* To stop warning. */
+ grub_register_command ("test_crontab", grub_cmd_test_crontab,
+ GRUB_COMMAND_FLAG_BOTH,
+ "test_crontab min hour day_of_month month day_of_week",
+ "Command to test current datetime.", 0);
+}
+
+GRUB_MOD_FINI(crontab)
+{
+ grub_unregister_command ("test_crontab");
+}
diff --git a/commands/date.c b/commands/date.c
new file mode 100644
index 0000000..c181289
--- /dev/null
+++ b/commands/date.c
@@ -0,0 +1,125 @@
+/* date.c - command to display/set current datetime. */
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/datetime.h>
+
+static grub_err_t
+grub_cmd_date (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_datetime datetime;
+ char* dow_names[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+ int limit[6][2] = {{1980, 2079}, {1, 12}, {1, 31}, {0, 23}, {0, 59}, {0, 59}};
+ int value[6], mask;
+
+ if (argc == 0)
+ {
+ if (grub_get_datetime (&datetime))
+ return grub_errno;
+
+ grub_printf ("%d-%02d-%02d %02d:%02d:%02d %s\n",
+ datetime.year, datetime.month, datetime.day,
+ datetime.hour, datetime.minute, datetime.second,
+ dow_names[grub_get_day_of_week (&datetime)]);
+
+ return 0;
+ }
+
+ grub_memset (&value, 0, sizeof (value));
+ mask = 0;
+
+ for (; argc; argc--, args++)
+ {
+ char *p, c;
+ int m1, ofs, n, cur_mask;
+
+ p = args[0];
+ m1 = grub_strtoul (p, &p, 10);
+
+ c = *p;
+ if (c == '-')
+ ofs = 0;
+ else if (c == ':')
+ ofs = 3;
+ else
+ goto fail;
+
+ value[ofs] = m1;
+ cur_mask = (1 << ofs);
+ mask &= ~(cur_mask * (1 + 2 + 4));
+
+ for (n = 1; (n < 3) && (*p); n++)
+ {
+ if (*p != c)
+ goto fail;
+
+ value[ofs + n] = grub_strtoul (p + 1, &p, 10);
+ cur_mask |= (1 << (ofs + n));
+ }
+
+ if (*p)
+ goto fail;
+
+ if ((ofs == 0) && (n == 2))
+ {
+ value[ofs + 2] = value[ofs + 1];
+ value[ofs + 1] = value[ofs];
+ ofs++;
+ cur_mask <<= 1;
+ }
+
+ for (; n; n--, ofs++)
+ if ((value [ofs] < limit[ofs][0]) ||
+ (value [ofs] > limit[ofs][1]))
+ goto fail;
+
+ mask |= cur_mask;
+ }
+
+ datetime.year = value[0];
+ datetime.month = value[1];
+ datetime.day = value[2];
+ datetime.hour = value[3];
+ datetime.minute = value[4];
+ datetime.second = value[5];
+
+ return grub_set_datetime (&datetime, mask);
+
+fail:
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid datetime");
+}
+
+GRUB_MOD_INIT(date)
+{
+ (void) mod; /* To stop warning. */
+ grub_register_command ("date", grub_cmd_date,
+ GRUB_COMMAND_FLAG_BOTH,
+ "date [[year-]month-day] [hour:minute[:second]]",
+ "Command to display/set current datetime.", 0);
+}
+
+GRUB_MOD_FINI(date)
+{
+ grub_unregister_command ("date");
+}
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index 4827c0f..f2d5875 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -101,7 +101,7 @@ pkglib_MODULES = _linux.mod linux.mod normal.mod \
_multiboot.mod multiboot.mod aout.mod \
play.mod cpuid.mod serial.mod ata.mod \
memdisk.mod pci.mod lspci.mod reboot.mod \
- halt.mod
+ halt.mod datetime.mod date.mod crontab.mod
# For _linux.mod.
_linux_mod_SOURCES = loader/i386/pc/linux.c
@@ -186,4 +186,19 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = kern/i386/datetime.c kern/generic/get_dow.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For crontab.mod
+crontab_mod_SOURCES = commands/crontab.c
+crontab_mod_CFLAGS = $(COMMON_CFLAGS)
+crontab_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 2ce21b1..a7a2483 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -75,7 +75,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
- _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod
+ _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod \
+ datetime.mod date.mod crontab.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -167,4 +168,19 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = kern/efi/datetime.c kern/generic/get_dow.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For crontab.mod
+crontab_mod_SOURCES = commands/crontab.c
+crontab_mod_CFLAGS = $(COMMON_CFLAGS)
+crontab_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index a93845e..e6dc4bc 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -104,7 +104,8 @@ grub_install_SOURCES = util/ieee1275/grub-install.in
# Modules.
pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod cpuid.mod \
multiboot.mod _multiboot.mod aout.mod serial.mod linux.mod \
- _linux.mod nand.mod memdisk.mod pci.mod lspci.mod
+ _linux.mod nand.mod memdisk.mod pci.mod lspci.mod datetime.mod \
+ date.mod crontab.mod
# For normal.mod.
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
@@ -188,4 +189,19 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = kern/i386/datetime.c kern/generic/get_dow.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For crontab.mod
+crontab_mod_SOURCES = commands/crontab.c
+crontab_mod_CFLAGS = $(COMMON_CFLAGS)
+crontab_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index c1e4ac4..aa19219 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -163,7 +163,8 @@ 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 datetime.mod date.mod \
+ crontab.mod
# For biosdisk.mod.
biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -340,4 +341,19 @@ pxecmd_mod_SOURCES = commands/i386/pc/pxecmd.c
pxecmd_mod_CFLAGS = $(COMMON_CFLAGS)
pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = kern/i386/datetime.c kern/generic/get_dow.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For crontab.mod
+crontab_mod_SOURCES = commands/crontab.c
+crontab_mod_CFLAGS = $(COMMON_CFLAGS)
+crontab_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
index 4f8abba..194c436 100644
--- a/conf/x86_64-efi.rmk
+++ b/conf/x86_64-efi.rmk
@@ -77,7 +77,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
- cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod
+ cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod \
+ datetime.mod date.mod crontab.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -169,4 +170,19 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = kern/efi/datetime.c kern/generic/get_dow.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For crontab.mod
+crontab_mod_SOURCES = commands/crontab.c
+crontab_mod_CFLAGS = $(COMMON_CFLAGS)
+crontab_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/include/grub/datetime.h b/include/grub/datetime.h
new file mode 100644
index 0000000..b8c9f7e
--- /dev/null
+++ b/include/grub/datetime.h
@@ -0,0 +1,57 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_DATETIME_HEADER
+#define KERNEL_DATETIME_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+
+#define GRUB_DATETIME_SET_YEAR 1
+#define GRUB_DATETIME_SET_MONTH 2
+#define GRUB_DATETIME_SET_DAY 4
+#define GRUB_DATETIME_SET_DATE (GRUB_DATETIME_SET_YEAR | \
+ GRUB_DATETIME_SET_MONTH | \
+ GRUB_DATETIME_SET_DAY)
+
+#define GRUB_DATETIME_SET_HOUR 8
+#define GRUB_DATETIME_SET_MINUTE 16
+#define GRUB_DATETIME_SET_SECOND 32
+#define GRUB_DATETIME_SET_TIME (GRUB_DATETIME_SET_HOUR | \
+ GRUB_DATETIME_SET_MINUTE | \
+ GRUB_DATETIME_SET_SECOND)
+
+struct grub_datetime
+{
+ grub_uint16_t year;
+ grub_uint8_t month;
+ grub_uint8_t day;
+ grub_uint8_t hour;
+ grub_uint8_t minute;
+ grub_uint8_t second;
+};
+
+/* Return date and time. */
+grub_err_t grub_get_datetime (struct grub_datetime *datetime);
+
+/* Set date and time. */
+grub_err_t grub_set_datetime (struct grub_datetime *datetime, int mask);
+
+int grub_get_day_of_week (struct grub_datetime *datetime);
+
+#endif /* ! KERNEL_DATETIME_HEADER */
diff --git a/include/grub/i386/cmos.h b/include/grub/i386/cmos.h
new file mode 100644
index 0000000..d482a7d
--- /dev/null
+++ b/include/grub/i386/cmos.h
@@ -0,0 +1,74 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CPU_CMOS_H
+#define GRUB_CPU_CMOS_H 1
+
+#include <grub/types.h>
+#include <grub/i386/io.h>
+
+#define GRUB_CMOS_ADDR_REG 0x70
+#define GRUB_CMOS_DATA_REG 0x71
+
+#define GRUB_CMOS_INDEX_SECOND 0
+#define GRUB_CMOS_INDEX_SECOND_ALARM 1
+#define GRUB_CMOS_INDEX_MINUTE 2
+#define GRUB_CMOS_INDEX_MINUTE_ALARM 3
+#define GRUB_CMOS_INDEX_HOUR 4
+#define GRUB_CMOS_INDEX_HOUR_ALARM 5
+#define GRUB_CMOS_INDEX_DAY_OF_WEEK 6
+#define GRUB_CMOS_INDEX_DAY_OF_MONTH 7
+#define GRUB_CMOS_INDEX_MONTH 8
+#define GRUB_CMOS_INDEX_YEAR 9
+
+#define GRUB_CMOS_INDEX_STATUS_A 0xA
+#define GRUB_CMOS_INDEX_STATUS_B 0xB
+#define GRUB_CMOS_INDEX_STATUS_C 0xC
+#define GRUB_CMOS_INDEX_STATUS_D 0xD
+
+#define GRUB_CMOS_STATUS_B_DAYLIGHT 1
+#define GRUB_CMOS_STATUS_B_24HOUR 2
+#define GRUB_CMOS_STATUS_B_BINARY 4
+
+static inline grub_uint8_t
+grub_bcd_to_num (grub_uint8_t a)
+{
+ return ((a >> 4) * 10 + (a & 0xF));
+}
+
+static inline grub_uint8_t
+grub_num_to_bcd (grub_uint8_t a)
+{
+ return (((a / 10) << 4) + (a % 10));
+}
+
+static inline grub_uint8_t
+grub_cmos_read (grub_uint8_t index)
+{
+ grub_outb (index, GRUB_CMOS_ADDR_REG);
+ return grub_inb (GRUB_CMOS_DATA_REG);
+}
+
+static inline void
+grub_cmos_write (grub_uint8_t index, grub_uint8_t value)
+{
+ grub_outb (index, GRUB_CMOS_ADDR_REG);
+ grub_outb (value, GRUB_CMOS_DATA_REG);
+}
+
+#endif /* GRUB_CPU_PCI_H */
diff --git a/kern/efi/datetime.c b/kern/efi/datetime.c
new file mode 100644
index 0000000..4ba38be
--- /dev/null
+++ b/kern/efi/datetime.c
@@ -0,0 +1,87 @@
+/* kern/efi/datetime.c - efi datetime function.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/datetime.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+ grub_efi_status_t status;
+ struct grub_efi_time efi_time;
+
+ status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
+ &efi_time, 0);
+
+ if (status)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t get datetime");
+ else
+ {
+ datetime->year = efi_time.year;
+ datetime->month = efi_time.month;
+ datetime->day = efi_time.day;
+ datetime->hour = efi_time.hour;
+ datetime->minute = efi_time.minute;
+ datetime->second = efi_time.second;
+ }
+
+ return 0;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime, int mask)
+{
+ grub_efi_status_t status;
+ struct grub_efi_time efi_time;
+
+ status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
+ &efi_time, 0);
+
+ if (status)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t get datetime");
+
+ if (mask & GRUB_DATETIME_SET_YEAR)
+ efi_time.year = datetime->year;
+
+ if (mask & GRUB_DATETIME_SET_MONTH)
+ efi_time.month = datetime->month;
+
+ if (mask & GRUB_DATETIME_SET_DAY)
+ efi_time.day = datetime->day;
+
+ if (mask & GRUB_DATETIME_SET_HOUR)
+ efi_time.hour = datetime->hour;
+
+ if (mask & GRUB_DATETIME_SET_MINUTE)
+ efi_time.minute = datetime->minute;
+
+ if (mask & GRUB_DATETIME_SET_SECOND)
+ efi_time.second = datetime->second;
+
+ status = efi_call_1 (grub_efi_system_table->runtime_services->set_time,
+ &efi_time);
+
+ if (status)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t set datetime");
+
+ return 0;
+}
diff --git a/kern/generic/get_dow.c b/kern/generic/get_dow.c
new file mode 100755
index 0000000..fd1a032
--- /dev/null
+++ b/kern/generic/get_dow.c
@@ -0,0 +1,32 @@
+/* get_dow - Calculate the day of week. */
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/datetime.h>
+
+int
+grub_get_day_of_week (struct grub_datetime *datetime)
+{
+ int a, y, m;
+
+ a = (14 - datetime->month) / 12;
+ y = datetime->year - a;
+ m = datetime->month + 12 * a - 2;
+
+ return (datetime->day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7;
+}
diff --git a/kern/i386/datetime.c b/kern/i386/datetime.c
new file mode 100644
index 0000000..466a404
--- /dev/null
+++ b/kern/i386/datetime.c
@@ -0,0 +1,175 @@
+/* kern/i386/datetime.c - x86 CMOS datetime function.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/datetime.h>
+#include <grub/i386/cmos.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+ int is_bcd, is_12hour;
+ grub_uint8_t value, flag;
+
+ flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+
+ is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_YEAR);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->year = value;
+ datetime->year += (value < 80) ? 2000 : 1900;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->month = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->day = value;
+
+ is_12hour = ! (flag & GRUB_CMOS_STATUS_B_24HOUR);
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_HOUR);
+ if (is_12hour)
+ {
+ is_12hour = (value & 0x80);
+
+ value &= 0x7F;
+ value--;
+ }
+
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ if (is_12hour)
+ value += 12;
+
+ datetime->hour = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->minute = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_SECOND);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->second = value;
+
+ return 0;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime, int mask)
+{
+ int is_bcd;
+ grub_uint8_t value, flag;
+
+ flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+
+ is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
+
+ if (mask & GRUB_DATETIME_SET_YEAR)
+ {
+ value = ((datetime->year >= 2000) ? datetime->year - 2000 :
+ datetime->year - 1900);
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_MONTH)
+ {
+ value = datetime->month;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_DAY)
+ {
+ value = datetime->day;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_HOUR)
+ {
+ int is_12hour;
+
+ value = datetime->hour;
+
+ is_12hour = (! (flag & GRUB_CMOS_STATUS_B_24HOUR));
+
+ if (is_12hour)
+ {
+ value++;
+
+ if (value > 12)
+ value -= 12;
+ else
+ is_12hour = 0;
+ }
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ if (is_12hour)
+ value |= 0x80;
+
+ grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_MINUTE)
+ {
+ value = datetime->minute;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_SECOND)
+ {
+ value = datetime->second;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value);
+ }
+
+ return 0;
+}
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-09 4:34 ` Bean
@ 2008-08-09 11:20 ` Isaac Dupree
2008-08-09 11:37 ` Bean
0 siblings, 1 reply; 28+ messages in thread
From: Isaac Dupree @ 2008-08-09 11:20 UTC (permalink / raw)
To: The development of GRUB 2
Bean wrote:
> I agree with Colin the datetime representation should be more
> intuitive, but we should stick to one layout. I use the following
> format now:
>
> date [[year-]month-day] [hour:minute[:second]]
>
> date is separated by `-' , and time `:', year and second part can be omitted.
I'm also a fan of ISO 8601, which has similarities to that
above format
http://en.wikipedia.org/wiki/ISO_8601
(well, we may only want to use a subset of ISO 8601's formats.)
It did remind me since it has optional time zone info, that
time zones exist :-) ... does GRUB have any idea what the
local timezone is, or will it have to require the time-zone
part? What about whether the hardware clock is UTC or
local-time?
-Isaac
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-09 11:20 ` Isaac Dupree
@ 2008-08-09 11:37 ` Bean
2008-08-10 9:32 ` Robert Millan
0 siblings, 1 reply; 28+ messages in thread
From: Bean @ 2008-08-09 11:37 UTC (permalink / raw)
To: The development of GRUB 2
On Sat, Aug 9, 2008 at 7:20 PM, Isaac Dupree
<id@isaac.cedarswampstudios.org> wrote:
> Bean wrote:
>>
>> I agree with Colin the datetime representation should be more
>> intuitive, but we should stick to one layout. I use the following
>> format now:
>>
>> date [[year-]month-day] [hour:minute[:second]]
>>
>> date is separated by `-' , and time `:', year and second part can be
>> omitted.
>
> I'm also a fan of ISO 8601, which has similarities to that above format
> http://en.wikipedia.org/wiki/ISO_8601
> (well, we may only want to use a subset of ISO 8601's formats.)
>
> It did remind me since it has optional time zone info, that time zones exist
> :-) ... does GRUB have any idea what the local timezone is, or will it have
> to require the time-zone part? What about whether the hardware clock is UTC
> or local-time?
Hi,
The efi time service have time zone info, but pc cmos don't, although
we can assume it's 0. But since pc is the platform for most user, I
guess it's not very useful.
--
Bean
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-09 11:37 ` Bean
@ 2008-08-10 9:32 ` Robert Millan
2008-08-10 11:10 ` Bean
0 siblings, 1 reply; 28+ messages in thread
From: Robert Millan @ 2008-08-10 9:32 UTC (permalink / raw)
To: The development of GRUB 2
On Sat, Aug 09, 2008 at 07:37:02PM +0800, Bean wrote:
>
> Hi,
>
> The efi time service have time zone info, but pc cmos don't, although
> we can assume it's 0. But since pc is the platform for most user, I
> guess it's not very useful.
It wouldn't be hard to make update-grub gather time zone information from the
host system and put it in a variable in grub.cfg, or something like that.
--
Robert Millan
The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
how) you may access your data; but nobody's threatening your freedom: we
still allow you to remove your data and not access it at all."
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-10 9:32 ` Robert Millan
@ 2008-08-10 11:10 ` Bean
2008-08-10 15:15 ` Isaac Dupree
0 siblings, 1 reply; 28+ messages in thread
From: Bean @ 2008-08-10 11:10 UTC (permalink / raw)
To: The development of GRUB 2
On Sun, Aug 10, 2008 at 5:32 PM, Robert Millan <rmh@aybabtu.com> wrote:
> On Sat, Aug 09, 2008 at 07:37:02PM +0800, Bean wrote:
>>
>> Hi,
>>
>> The efi time service have time zone info, but pc cmos don't, although
>> we can assume it's 0. But since pc is the platform for most user, I
>> guess it's not very useful.
>
> It wouldn't be hard to make update-grub gather time zone information from the
> host system and put it in a variable in grub.cfg, or something like that.
Hi,
Oh right, but the handling of timezone is not trivial, especially when
it across date boundary. Perhaps we just ignore it for now.
--
Bean
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-10 11:10 ` Bean
@ 2008-08-10 15:15 ` Isaac Dupree
2008-08-10 17:22 ` Robert Millan
0 siblings, 1 reply; 28+ messages in thread
From: Isaac Dupree @ 2008-08-10 15:15 UTC (permalink / raw)
To: The development of GRUB 2
Bean wrote:
> On Sun, Aug 10, 2008 at 5:32 PM, Robert Millan <rmh@aybabtu.com> wrote:
>> It wouldn't be hard to make update-grub gather time zone information from the
>> host system and put it in a variable in grub.cfg, or something like that.
>
> Hi,
>
> Oh right, but the handling of timezone is not trivial, especially when
> it across date boundary. Perhaps we just ignore it for now.
also, even if one's computer always stays in the same place,
Daylight Savings can change the timezone you're in, while
grub.cfg stays the same.
What is it that we're doing when we "ignore" it
specifically? Assuming local-time and hardware-clock-time
are both UTC? (and therefore if the date specifies a
timezone, which is specified numerically, convert the time
to UTC before doing anything with it)
(The above behavior means that if the hardware-clock is
actually local time, one could specify the time without a
timezone / with timezone Z, and it will work to set the
time, despite the incorrect assumptions.)
-Isaac
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-10 15:15 ` Isaac Dupree
@ 2008-08-10 17:22 ` Robert Millan
0 siblings, 0 replies; 28+ messages in thread
From: Robert Millan @ 2008-08-10 17:22 UTC (permalink / raw)
To: The development of GRUB 2
On Sun, Aug 10, 2008 at 11:15:53AM -0400, Isaac Dupree wrote:
>
> also, even if one's computer always stays in the same place,
> Daylight Savings can change the timezone you're in, while
> grub.cfg stays the same.
>
> What is it that we're doing when we "ignore" it
> specifically? Assuming local-time and hardware-clock-time
> are both UTC? (and therefore if the date specifies a
> timezone, which is specified numerically, convert the time
> to UTC before doing anything with it)
The hwclock time is always the same as UTC; except for some very weird
OSes like Microsoft Windows ;-)
--
Robert Millan
The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
how) you may access your data; but nobody's threatening your freedom: we
still allow you to remove your data and not access it at all."
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-06 11:02 [PATCH] New command checktime Bean
2008-08-06 11:35 ` Robert Millan
@ 2008-08-10 18:04 ` Marco Gerards
2008-08-11 11:06 ` Bean
1 sibling, 1 reply; 28+ messages in thread
From: Marco Gerards @ 2008-08-10 18:04 UTC (permalink / raw)
To: The development of GRUB 2
Hi,
Bean <bean123ch@gmail.com> writes:
> I implement this command for grub4dos some time ago, now it's ported to grub2.
>
> Usage:
>
> checktime min hour day_of_month month day_of_week
Personally I would prefer it if it worked a bit more GRUB2/bash like.
So can you make this variables?
For example:
if ($WEEKDAY = Sunday); then
...
fi
The same can be done for all week number, day number, year, etc, etc.
The advantage of this is that many users are familiar with such syntax
and it will give them more control. Furthermore, this is what I
intended with the scripting support in the first place. So can you
please follow such scheme?
--
Marco
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-10 18:04 ` Marco Gerards
@ 2008-08-11 11:06 ` Bean
2008-08-11 14:18 ` Robert Millan
2008-08-11 21:07 ` Marco Gerards
0 siblings, 2 replies; 28+ messages in thread
From: Bean @ 2008-08-11 11:06 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 2578 bytes --]
On Mon, Aug 11, 2008 at 2:04 AM, Marco Gerards <mgerards@xs4all.nl> wrote:
> Hi,
>
> Bean <bean123ch@gmail.com> writes:
>
>> I implement this command for grub4dos some time ago, now it's ported to grub2.
>>
>> Usage:
>>
>> checktime min hour day_of_month month day_of_week
>
> Personally I would prefer it if it worked a bit more GRUB2/bash like.
> So can you make this variables?
>
> For example:
>
> if ($WEEKDAY = Sunday); then
> ...
> fi
>
> The same can be done for all week number, day number, year, etc, etc.
>
> The advantage of this is that many users are familiar with such syntax
> and it will give them more control. Furthermore, this is what I
> intended with the scripting support in the first place. So can you
> please follow such scheme?
Hi,
As suggested by marco, this patch replaces the crontab command with
variable hook. Now you can retrive current date/time with variable
$YEAR, $MONTH, $DAY, $HOUR, $MINUTE, $SECOND and $WEEKDAY.
2008-08-11 Bean <bean123ch@gmail.com>
* conf/i386-pc.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
* conf/i386-coreboot.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
* conf/i386-ieee1275.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
* conf/i386-efi.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
* conf/x86_64-efi.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
* commands/date.c: New file.
* commands/datetime.c: Likewise.
* include/grub/datetime.h: Likewise.
* include/grub/i386/cmos.h: Likewise.
* kern/i386/datetime.c: Likewise.
* kern/efi/datetime.c: Likewise.
--
Bean
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: date_3.diff --]
[-- Type: text/x-diff; name=date_3.diff, Size: 23139 bytes --]
diff --git a/commands/date.c b/commands/date.c
new file mode 100644
index 0000000..1e11e61
--- /dev/null
+++ b/commands/date.c
@@ -0,0 +1,124 @@
+/* date.c - command to display/set current datetime. */
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/datetime.h>
+
+static grub_err_t
+grub_cmd_date (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_datetime datetime;
+ int limit[6][2] = {{1980, 2079}, {1, 12}, {1, 31}, {0, 23}, {0, 59}, {0, 59}};
+ int value[6], mask;
+
+ if (argc == 0)
+ {
+ if (grub_get_datetime (&datetime))
+ return grub_errno;
+
+ grub_printf ("%d-%02d-%02d %02d:%02d:%02d %s\n",
+ datetime.year, datetime.month, datetime.day,
+ datetime.hour, datetime.minute, datetime.second,
+ grub_get_weekday_name (&datetime));
+
+ return 0;
+ }
+
+ grub_memset (&value, 0, sizeof (value));
+ mask = 0;
+
+ for (; argc; argc--, args++)
+ {
+ char *p, c;
+ int m1, ofs, n, cur_mask;
+
+ p = args[0];
+ m1 = grub_strtoul (p, &p, 10);
+
+ c = *p;
+ if (c == '-')
+ ofs = 0;
+ else if (c == ':')
+ ofs = 3;
+ else
+ goto fail;
+
+ value[ofs] = m1;
+ cur_mask = (1 << ofs);
+ mask &= ~(cur_mask * (1 + 2 + 4));
+
+ for (n = 1; (n < 3) && (*p); n++)
+ {
+ if (*p != c)
+ goto fail;
+
+ value[ofs + n] = grub_strtoul (p + 1, &p, 10);
+ cur_mask |= (1 << (ofs + n));
+ }
+
+ if (*p)
+ goto fail;
+
+ if ((ofs == 0) && (n == 2))
+ {
+ value[ofs + 2] = value[ofs + 1];
+ value[ofs + 1] = value[ofs];
+ ofs++;
+ cur_mask <<= 1;
+ }
+
+ for (; n; n--, ofs++)
+ if ((value [ofs] < limit[ofs][0]) ||
+ (value [ofs] > limit[ofs][1]))
+ goto fail;
+
+ mask |= cur_mask;
+ }
+
+ datetime.year = value[0];
+ datetime.month = value[1];
+ datetime.day = value[2];
+ datetime.hour = value[3];
+ datetime.minute = value[4];
+ datetime.second = value[5];
+
+ return grub_set_datetime (&datetime, mask);
+
+fail:
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid datetime");
+}
+
+GRUB_MOD_INIT(date)
+{
+ (void) mod; /* To stop warning. */
+ grub_register_command ("date", grub_cmd_date,
+ GRUB_COMMAND_FLAG_BOTH,
+ "date [[year-]month-day] [hour:minute[:second]]",
+ "Command to display/set current datetime.", 0);
+}
+
+GRUB_MOD_FINI(date)
+{
+ grub_unregister_command ("date");
+}
diff --git a/commands/datetime.c b/commands/datetime.c
new file mode 100644
index 0000000..a681f96
--- /dev/null
+++ b/commands/datetime.c
@@ -0,0 +1,132 @@
+/* datetime.c - Module to export datetime variables. */
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/datetime.h>
+
+static char *grub_weekday_names[] =
+{
+ "Sunday",
+ "Monday",
+ "Tueday",
+ "Wednesday",
+ "Thusday",
+ "Friday",
+ "Saturday",
+};
+
+static char *grub_datetime_names[] =
+{
+ "YEAR",
+ "MONTH",
+ "DAY",
+ "HOUR",
+ "MINUTE",
+ "SECOND",
+ "WEEKDAY",
+};
+
+int
+grub_get_weekday (struct grub_datetime *datetime)
+{
+ int a, y, m;
+
+ a = (14 - datetime->month) / 12;
+ y = datetime->year - a;
+ m = datetime->month + 12 * a - 2;
+
+ return (datetime->day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7;
+}
+
+char *
+grub_get_weekday_name (struct grub_datetime *datetime)
+{
+ return grub_weekday_names[grub_get_weekday (datetime)];
+}
+
+static char *
+grub_read_hook_datetime (struct grub_env_var *var,
+ const char *val __attribute__ ((unused)))
+{
+ struct grub_datetime datetime;
+ static char buf[6];
+
+ buf[0] = 0;
+ if (! grub_get_datetime (&datetime))
+ {
+ int i;
+
+ for (i = 0; i < 7; i++)
+ if (! grub_strcmp (var->name, grub_datetime_names[i]))
+ {
+ int n;
+
+ switch (i)
+ {
+ case 0:
+ n = datetime.year;
+ break;
+ case 1:
+ n = datetime.month;
+ break;
+ case 2:
+ n = datetime.day;
+ break;
+ case 3:
+ n = datetime.hour;
+ break;
+ case 4:
+ n = datetime.minute;
+ break;
+ case 5:
+ n = datetime.second;
+ break;
+ default:
+ return grub_get_weekday_name (&datetime);
+ }
+
+ grub_sprintf (buf, "%d", n);
+ break;
+ }
+ }
+
+ return buf;
+}
+
+GRUB_MOD_INIT(datetime)
+{
+ (void)mod; /* To stop warning. */
+ int i;
+
+ for (i = 0; i < 7; i++)
+ grub_register_variable_hook (grub_datetime_names[i],
+ grub_read_hook_datetime, 0);
+}
+
+GRUB_MOD_FINI(datetime)
+{
+ int i;
+
+ for (i = 0; i < 7; i++)
+ grub_register_variable_hook (grub_datetime_names[i], 0, 0);
+}
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index 4827c0f..2ec34a6 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -101,7 +101,7 @@ pkglib_MODULES = _linux.mod linux.mod normal.mod \
_multiboot.mod multiboot.mod aout.mod \
play.mod cpuid.mod serial.mod ata.mod \
memdisk.mod pci.mod lspci.mod reboot.mod \
- halt.mod
+ halt.mod datetime.mod date.mod
# For _linux.mod.
_linux_mod_SOURCES = loader/i386/pc/linux.c
@@ -186,4 +186,14 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = commands/datetime.c kern/i386/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 2ce21b1..8556954 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -75,7 +75,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
- _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod
+ _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod \
+ datetime.mod date.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -167,4 +168,14 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = commands/datetime.c kern/efi/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index a93845e..5728c5c 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -104,7 +104,8 @@ grub_install_SOURCES = util/ieee1275/grub-install.in
# Modules.
pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod cpuid.mod \
multiboot.mod _multiboot.mod aout.mod serial.mod linux.mod \
- _linux.mod nand.mod memdisk.mod pci.mod lspci.mod
+ _linux.mod nand.mod memdisk.mod pci.mod lspci.mod datetime.mod \
+ date.mod
# For normal.mod.
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
@@ -188,4 +189,14 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = commands/datetime.c kern/i386/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index c1e4ac4..f9c6b4f 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -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 datetime.mod date.mod
# For biosdisk.mod.
biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -340,4 +340,14 @@ pxecmd_mod_SOURCES = commands/i386/pc/pxecmd.c
pxecmd_mod_CFLAGS = $(COMMON_CFLAGS)
pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = commands/datetime.c kern/i386/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
index 4f8abba..4fdfa9a 100644
--- a/conf/x86_64-efi.rmk
+++ b/conf/x86_64-efi.rmk
@@ -77,7 +77,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
- cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod
+ cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod \
+ datetime.mod date.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -169,4 +170,14 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = commands/datetime.c kern/efi/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/include/grub/datetime.h b/include/grub/datetime.h
new file mode 100644
index 0000000..3fb5e50
--- /dev/null
+++ b/include/grub/datetime.h
@@ -0,0 +1,58 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_DATETIME_HEADER
+#define KERNEL_DATETIME_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+
+#define GRUB_DATETIME_SET_YEAR 1
+#define GRUB_DATETIME_SET_MONTH 2
+#define GRUB_DATETIME_SET_DAY 4
+#define GRUB_DATETIME_SET_DATE (GRUB_DATETIME_SET_YEAR | \
+ GRUB_DATETIME_SET_MONTH | \
+ GRUB_DATETIME_SET_DAY)
+
+#define GRUB_DATETIME_SET_HOUR 8
+#define GRUB_DATETIME_SET_MINUTE 16
+#define GRUB_DATETIME_SET_SECOND 32
+#define GRUB_DATETIME_SET_TIME (GRUB_DATETIME_SET_HOUR | \
+ GRUB_DATETIME_SET_MINUTE | \
+ GRUB_DATETIME_SET_SECOND)
+
+struct grub_datetime
+{
+ grub_uint16_t year;
+ grub_uint8_t month;
+ grub_uint8_t day;
+ grub_uint8_t hour;
+ grub_uint8_t minute;
+ grub_uint8_t second;
+};
+
+/* Return date and time. */
+grub_err_t grub_get_datetime (struct grub_datetime *datetime);
+
+/* Set date and time. */
+grub_err_t grub_set_datetime (struct grub_datetime *datetime, int mask);
+
+int grub_get_weekday (struct grub_datetime *datetime);
+char *grub_get_weekday_name (struct grub_datetime *datetime);
+
+#endif /* ! KERNEL_DATETIME_HEADER */
diff --git a/include/grub/i386/cmos.h b/include/grub/i386/cmos.h
new file mode 100644
index 0000000..d482a7d
--- /dev/null
+++ b/include/grub/i386/cmos.h
@@ -0,0 +1,74 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CPU_CMOS_H
+#define GRUB_CPU_CMOS_H 1
+
+#include <grub/types.h>
+#include <grub/i386/io.h>
+
+#define GRUB_CMOS_ADDR_REG 0x70
+#define GRUB_CMOS_DATA_REG 0x71
+
+#define GRUB_CMOS_INDEX_SECOND 0
+#define GRUB_CMOS_INDEX_SECOND_ALARM 1
+#define GRUB_CMOS_INDEX_MINUTE 2
+#define GRUB_CMOS_INDEX_MINUTE_ALARM 3
+#define GRUB_CMOS_INDEX_HOUR 4
+#define GRUB_CMOS_INDEX_HOUR_ALARM 5
+#define GRUB_CMOS_INDEX_DAY_OF_WEEK 6
+#define GRUB_CMOS_INDEX_DAY_OF_MONTH 7
+#define GRUB_CMOS_INDEX_MONTH 8
+#define GRUB_CMOS_INDEX_YEAR 9
+
+#define GRUB_CMOS_INDEX_STATUS_A 0xA
+#define GRUB_CMOS_INDEX_STATUS_B 0xB
+#define GRUB_CMOS_INDEX_STATUS_C 0xC
+#define GRUB_CMOS_INDEX_STATUS_D 0xD
+
+#define GRUB_CMOS_STATUS_B_DAYLIGHT 1
+#define GRUB_CMOS_STATUS_B_24HOUR 2
+#define GRUB_CMOS_STATUS_B_BINARY 4
+
+static inline grub_uint8_t
+grub_bcd_to_num (grub_uint8_t a)
+{
+ return ((a >> 4) * 10 + (a & 0xF));
+}
+
+static inline grub_uint8_t
+grub_num_to_bcd (grub_uint8_t a)
+{
+ return (((a / 10) << 4) + (a % 10));
+}
+
+static inline grub_uint8_t
+grub_cmos_read (grub_uint8_t index)
+{
+ grub_outb (index, GRUB_CMOS_ADDR_REG);
+ return grub_inb (GRUB_CMOS_DATA_REG);
+}
+
+static inline void
+grub_cmos_write (grub_uint8_t index, grub_uint8_t value)
+{
+ grub_outb (index, GRUB_CMOS_ADDR_REG);
+ grub_outb (value, GRUB_CMOS_DATA_REG);
+}
+
+#endif /* GRUB_CPU_PCI_H */
diff --git a/kern/efi/datetime.c b/kern/efi/datetime.c
new file mode 100644
index 0000000..4ba38be
--- /dev/null
+++ b/kern/efi/datetime.c
@@ -0,0 +1,87 @@
+/* kern/efi/datetime.c - efi datetime function.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/datetime.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+ grub_efi_status_t status;
+ struct grub_efi_time efi_time;
+
+ status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
+ &efi_time, 0);
+
+ if (status)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t get datetime");
+ else
+ {
+ datetime->year = efi_time.year;
+ datetime->month = efi_time.month;
+ datetime->day = efi_time.day;
+ datetime->hour = efi_time.hour;
+ datetime->minute = efi_time.minute;
+ datetime->second = efi_time.second;
+ }
+
+ return 0;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime, int mask)
+{
+ grub_efi_status_t status;
+ struct grub_efi_time efi_time;
+
+ status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
+ &efi_time, 0);
+
+ if (status)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t get datetime");
+
+ if (mask & GRUB_DATETIME_SET_YEAR)
+ efi_time.year = datetime->year;
+
+ if (mask & GRUB_DATETIME_SET_MONTH)
+ efi_time.month = datetime->month;
+
+ if (mask & GRUB_DATETIME_SET_DAY)
+ efi_time.day = datetime->day;
+
+ if (mask & GRUB_DATETIME_SET_HOUR)
+ efi_time.hour = datetime->hour;
+
+ if (mask & GRUB_DATETIME_SET_MINUTE)
+ efi_time.minute = datetime->minute;
+
+ if (mask & GRUB_DATETIME_SET_SECOND)
+ efi_time.second = datetime->second;
+
+ status = efi_call_1 (grub_efi_system_table->runtime_services->set_time,
+ &efi_time);
+
+ if (status)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t set datetime");
+
+ return 0;
+}
diff --git a/kern/i386/datetime.c b/kern/i386/datetime.c
new file mode 100644
index 0000000..466a404
--- /dev/null
+++ b/kern/i386/datetime.c
@@ -0,0 +1,175 @@
+/* kern/i386/datetime.c - x86 CMOS datetime function.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/datetime.h>
+#include <grub/i386/cmos.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+ int is_bcd, is_12hour;
+ grub_uint8_t value, flag;
+
+ flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+
+ is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_YEAR);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->year = value;
+ datetime->year += (value < 80) ? 2000 : 1900;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->month = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->day = value;
+
+ is_12hour = ! (flag & GRUB_CMOS_STATUS_B_24HOUR);
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_HOUR);
+ if (is_12hour)
+ {
+ is_12hour = (value & 0x80);
+
+ value &= 0x7F;
+ value--;
+ }
+
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ if (is_12hour)
+ value += 12;
+
+ datetime->hour = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->minute = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_SECOND);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->second = value;
+
+ return 0;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime, int mask)
+{
+ int is_bcd;
+ grub_uint8_t value, flag;
+
+ flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+
+ is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
+
+ if (mask & GRUB_DATETIME_SET_YEAR)
+ {
+ value = ((datetime->year >= 2000) ? datetime->year - 2000 :
+ datetime->year - 1900);
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_MONTH)
+ {
+ value = datetime->month;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_DAY)
+ {
+ value = datetime->day;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_HOUR)
+ {
+ int is_12hour;
+
+ value = datetime->hour;
+
+ is_12hour = (! (flag & GRUB_CMOS_STATUS_B_24HOUR));
+
+ if (is_12hour)
+ {
+ value++;
+
+ if (value > 12)
+ value -= 12;
+ else
+ is_12hour = 0;
+ }
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ if (is_12hour)
+ value |= 0x80;
+
+ grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_MINUTE)
+ {
+ value = datetime->minute;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value);
+ }
+
+ if (mask & GRUB_DATETIME_SET_SECOND)
+ {
+ value = datetime->second;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value);
+ }
+
+ return 0;
+}
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-11 11:06 ` Bean
@ 2008-08-11 14:18 ` Robert Millan
2008-08-11 21:07 ` Marco Gerards
1 sibling, 0 replies; 28+ messages in thread
From: Robert Millan @ 2008-08-11 14:18 UTC (permalink / raw)
To: The development of GRUB 2
On Mon, Aug 11, 2008 at 07:06:11PM +0800, Bean wrote:
> --- /dev/null
> +++ b/commands/datetime.c
> @@ -0,0 +1,132 @@
> +/* datetime.c - Module to export datetime variables. */
Shouldn't this be somewhere else? (other than commands/)
--
Robert Millan
The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
how) you may access your data; but nobody's threatening your freedom: we
still allow you to remove your data and not access it at all."
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-11 11:06 ` Bean
2008-08-11 14:18 ` Robert Millan
@ 2008-08-11 21:07 ` Marco Gerards
2008-08-12 17:13 ` Bean
1 sibling, 1 reply; 28+ messages in thread
From: Marco Gerards @ 2008-08-11 21:07 UTC (permalink / raw)
To: The development of GRUB 2
Bean <bean123ch@gmail.com> writes:
> On Mon, Aug 11, 2008 at 2:04 AM, Marco Gerards <mgerards@xs4all.nl> wrote:
>> Hi,
>>
>> Bean <bean123ch@gmail.com> writes:
>>
>>> I implement this command for grub4dos some time ago, now it's ported to grub2.
>>>
>>> Usage:
>>>
>>> checktime min hour day_of_month month day_of_week
>>
>> Personally I would prefer it if it worked a bit more GRUB2/bash like.
>> So can you make this variables?
>>
>> For example:
>>
>> if ($WEEKDAY = Sunday); then
>> ...
>> fi
>>
>> The same can be done for all week number, day number, year, etc, etc.
>>
>> The advantage of this is that many users are familiar with such syntax
>> and it will give them more control. Furthermore, this is what I
>> intended with the scripting support in the first place. So can you
>> please follow such scheme?
>
> Hi,
>
> As suggested by marco, this patch replaces the crontab command with
> variable hook. Now you can retrive current date/time with variable
> $YEAR, $MONTH, $DAY, $HOUR, $MINUTE, $SECOND and $WEEKDAY.
>
> 2008-08-11 Bean <bean123ch@gmail.com>
>
> * conf/i386-pc.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
> (datetime_mod_SOURCES): New macro.
> (datetime_mod_CFLAGS): Likewise.
> (datetime_mod_LDFLAGS): Likewise.
> (date_mod_SOURCES): Likewise.
> (date_mod_CFLAGS): Likewise.
> (date_mod_LDFLAGS): Likewise.
>
> * conf/i386-coreboot.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
> (datetime_mod_SOURCES): New macro.
> (datetime_mod_CFLAGS): Likewise.
> (datetime_mod_LDFLAGS): Likewise.
> (date_mod_SOURCES): Likewise.
> (date_mod_CFLAGS): Likewise.
> (date_mod_LDFLAGS): Likewise.
>
> * conf/i386-ieee1275.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
> (datetime_mod_SOURCES): New macro.
> (datetime_mod_CFLAGS): Likewise.
> (datetime_mod_LDFLAGS): Likewise.
> (date_mod_SOURCES): Likewise.
> (date_mod_CFLAGS): Likewise.
> (date_mod_LDFLAGS): Likewise.
>
> * conf/i386-efi.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
> (datetime_mod_SOURCES): New macro.
> (datetime_mod_CFLAGS): Likewise.
> (datetime_mod_LDFLAGS): Likewise.
> (date_mod_SOURCES): Likewise.
> (date_mod_CFLAGS): Likewise.
> (date_mod_LDFLAGS): Likewise.
>
> * conf/x86_64-efi.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
> (datetime_mod_SOURCES): New macro.
> (datetime_mod_CFLAGS): Likewise.
> (datetime_mod_LDFLAGS): Likewise.
> (date_mod_SOURCES): Likewise.
> (date_mod_CFLAGS): Likewise.
> (date_mod_LDFLAGS): Likewise.
Robert is right, we need an i386.rmk or similar file.
> * commands/date.c: New file.
>
> * commands/datetime.c: Likewise.
This is not a command. But I do not really know a good place for this
module...
> * include/grub/datetime.h: Likewise.
>
> * include/grub/i386/cmos.h: Likewise.
>
> * kern/i386/datetime.c: Likewise.
>
> * kern/efi/datetime.c: Likewise.
Does this really belong in the kernel? You created lib/ (which I
still not might agree with, but ok ;)). But that might be a better
place than here.
> --
> Bean
>
> diff --git a/commands/date.c b/commands/date.c
> new file mode 100644
> index 0000000..1e11e61
> --- /dev/null
> +++ b/commands/date.c
> @@ -0,0 +1,124 @@
> +/* date.c - command to display/set current datetime. */
> +/*
> + * 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 <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/normal.h>
> +#include <grub/dl.h>
> +#include <grub/arg.h>
> +#include <grub/err.h>
> +#include <grub/misc.h>
> +#include <grub/datetime.h>
> +
> +static grub_err_t
> +grub_cmd_date (struct grub_arg_list *state __attribute__ ((unused)),
> + int argc, char **args)
> +{
> + struct grub_datetime datetime;
> + int limit[6][2] = {{1980, 2079}, {1, 12}, {1, 31}, {0, 23}, {0, 59}, {0, 59}};
> + int value[6], mask;
> +
> + if (argc == 0)
> + {
> + if (grub_get_datetime (&datetime))
> + return grub_errno;
> +
> + grub_printf ("%d-%02d-%02d %02d:%02d:%02d %s\n",
> + datetime.year, datetime.month, datetime.day,
> + datetime.hour, datetime.minute, datetime.second,
> + grub_get_weekday_name (&datetime));
> +
> + return 0;
> + }
Can you somehow use the argument parser here? This will give us
--help for free :-)
> + grub_memset (&value, 0, sizeof (value));
> + mask = 0;
> +
> + for (; argc; argc--, args++)
> + {
> + char *p, c;
> + int m1, ofs, n, cur_mask;
> +
> + p = args[0];
> + m1 = grub_strtoul (p, &p, 10);
> +
> + c = *p;
> + if (c == '-')
> + ofs = 0;
> + else if (c == ':')
> + ofs = 3;
> + else
> + goto fail;
> +
> + value[ofs] = m1;
> + cur_mask = (1 << ofs);
> + mask &= ~(cur_mask * (1 + 2 + 4));
> +
> + for (n = 1; (n < 3) && (*p); n++)
> + {
> + if (*p != c)
> + goto fail;
> +
> + value[ofs + n] = grub_strtoul (p + 1, &p, 10);
> + cur_mask |= (1 << (ofs + n));
> + }
> +
> + if (*p)
> + goto fail;
> +
> + if ((ofs == 0) && (n == 2))
> + {
> + value[ofs + 2] = value[ofs + 1];
> + value[ofs + 1] = value[ofs];
> + ofs++;
> + cur_mask <<= 1;
> + }
> +
> + for (; n; n--, ofs++)
> + if ((value [ofs] < limit[ofs][0]) ||
> + (value [ofs] > limit[ofs][1]))
> + goto fail;
> +
> + mask |= cur_mask;
> + }
> +
> + datetime.year = value[0];
> + datetime.month = value[1];
> + datetime.day = value[2];
> + datetime.hour = value[3];
> + datetime.minute = value[4];
> + datetime.second = value[5];
> +
> + return grub_set_datetime (&datetime, mask);
> +
> +fail:
> + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid datetime");
> +}
> +
> +GRUB_MOD_INIT(date)
> +{
> + (void) mod; /* To stop warning. */
> + grub_register_command ("date", grub_cmd_date,
> + GRUB_COMMAND_FLAG_BOTH,
> + "date [[year-]month-day] [hour:minute[:second]]",
This help string will not be shown if you do not use the argument
parser to generate a --help
Furthermore, I can imagine more arguments should be added in the future.
> + "Command to display/set current datetime.", 0);
> +}
> +
> +GRUB_MOD_FINI(date)
> +{
> + grub_unregister_command ("date");
> +}
> diff --git a/commands/datetime.c b/commands/datetime.c
> new file mode 100644
> index 0000000..a681f96
> --- /dev/null
> +++ b/commands/datetime.c
> @@ -0,0 +1,132 @@
> +/* datetime.c - Module to export datetime variables. */
> +/*
> + * 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 <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/types.h>
> +#include <grub/dl.h>
> +#include <grub/env.h>
> +#include <grub/misc.h>
> +#include <grub/normal.h>
> +#include <grub/datetime.h>
> +
> +static char *grub_weekday_names[] =
> +{
> + "Sunday",
> + "Monday",
> + "Tueday",
Tuesday
> + "Wednesday",
> + "Thusday",
Thursday
> + "Friday",
> + "Saturday",
> +};
Please notice that, depending on the country, the week either starts
on sunday or monday. Altough I am quite clueless about the specifics ;)
> +static char *grub_datetime_names[] =
> +{
> + "YEAR",
> + "MONTH",
> + "DAY",
> + "HOUR",
> + "MINUTE",
> + "SECOND",
> + "WEEKDAY",
> +};
> +
> +int
> +grub_get_weekday (struct grub_datetime *datetime)
> +{
> + int a, y, m;
> +
> + a = (14 - datetime->month) / 12;
> + y = datetime->year - a;
> + m = datetime->month + 12 * a - 2;
> +
> + return (datetime->day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7;
Wow ;-)
Does this deal with leap years?
> +}
> +
> +char *
> +grub_get_weekday_name (struct grub_datetime *datetime)
> +{
> + return grub_weekday_names[grub_get_weekday (datetime)];
> +}
Shoudn't this be static? Or is this intentional?
> +static char *
> +grub_read_hook_datetime (struct grub_env_var *var,
> + const char *val __attribute__ ((unused)))
> +{
> + struct grub_datetime datetime;
> + static char buf[6];
> +
> + buf[0] = 0;
> + if (! grub_get_datetime (&datetime))
> + {
> + int i;
> +
> + for (i = 0; i < 7; i++)
> + if (! grub_strcmp (var->name, grub_datetime_names[i]))
> + {
> + int n;
> +
> + switch (i)
> + {
> + case 0:
> + n = datetime.year;
> + break;
> + case 1:
> + n = datetime.month;
> + break;
> + case 2:
> + n = datetime.day;
> + break;
> + case 3:
> + n = datetime.hour;
> + break;
> + case 4:
> + n = datetime.minute;
> + break;
> + case 5:
> + n = datetime.second;
> + break;
> + default:
> + return grub_get_weekday_name (&datetime);
> + }
> +
> + grub_sprintf (buf, "%d", n);
> + break;
> + }
> + }
> +
> + return buf;
> +}
> +
> +GRUB_MOD_INIT(datetime)
> +{
> + (void)mod; /* To stop warning. */
> + int i;
> +
> + for (i = 0; i < 7; i++)
> + grub_register_variable_hook (grub_datetime_names[i],
> + grub_read_hook_datetime, 0);
> +}
> +
> +GRUB_MOD_FINI(datetime)
> +{
> + int i;
> +
> + for (i = 0; i < 7; i++)
> + grub_register_variable_hook (grub_datetime_names[i], 0, 0);
Perhaps it is even wise to unset the variables? As the contents are
no longer valid.
> +}
> diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
> index 4827c0f..2ec34a6 100644
> --- a/conf/i386-coreboot.rmk
> +++ b/conf/i386-coreboot.rmk
> @@ -101,7 +101,7 @@ pkglib_MODULES = _linux.mod linux.mod normal.mod \
> _multiboot.mod multiboot.mod aout.mod \
> play.mod cpuid.mod serial.mod ata.mod \
> memdisk.mod pci.mod lspci.mod reboot.mod \
> - halt.mod
> + halt.mod datetime.mod date.mod
>
> # For _linux.mod.
> _linux_mod_SOURCES = loader/i386/pc/linux.c
> @@ -186,4 +186,14 @@ lspci_mod_SOURCES = commands/lspci.c
> lspci_mod_CFLAGS = $(COMMON_CFLAGS)
> lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
>
> +# For datetime.mod
> +datetime_mod_SOURCES = commands/datetime.c kern/i386/datetime.c
> +datetime_mod_CFLAGS = $(COMMON_CFLAGS)
> +datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> +# For date.mod
> +date_mod_SOURCES = commands/date.c
> +date_mod_CFLAGS = $(COMMON_CFLAGS)
> +date_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> include $(srcdir)/conf/common.mk
> diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
> index 2ce21b1..8556954 100644
> --- a/conf/i386-efi.rmk
> +++ b/conf/i386-efi.rmk
> @@ -75,7 +75,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
>
> # Modules.
> pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
> - _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod
> + _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod \
> + datetime.mod date.mod
>
> # For kernel.mod.
> kernel_mod_EXPORTS = no
> @@ -167,4 +168,14 @@ lspci_mod_SOURCES = commands/lspci.c
> lspci_mod_CFLAGS = $(COMMON_CFLAGS)
> lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
>
> +# For datetime.mod
> +datetime_mod_SOURCES = commands/datetime.c kern/efi/datetime.c
> +datetime_mod_CFLAGS = $(COMMON_CFLAGS)
> +datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> +# For date.mod
> +date_mod_SOURCES = commands/date.c
> +date_mod_CFLAGS = $(COMMON_CFLAGS)
> +date_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> include $(srcdir)/conf/common.mk
> diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
> index a93845e..5728c5c 100644
> --- a/conf/i386-ieee1275.rmk
> +++ b/conf/i386-ieee1275.rmk
> @@ -104,7 +104,8 @@ grub_install_SOURCES = util/ieee1275/grub-install.in
> # Modules.
> pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod cpuid.mod \
> multiboot.mod _multiboot.mod aout.mod serial.mod linux.mod \
> - _linux.mod nand.mod memdisk.mod pci.mod lspci.mod
> + _linux.mod nand.mod memdisk.mod pci.mod lspci.mod datetime.mod \
> + date.mod
>
> # For normal.mod.
> normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
> @@ -188,4 +189,14 @@ lspci_mod_SOURCES = commands/lspci.c
> lspci_mod_CFLAGS = $(COMMON_CFLAGS)
> lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
>
> +# For datetime.mod
> +datetime_mod_SOURCES = commands/datetime.c kern/i386/datetime.c
> +datetime_mod_CFLAGS = $(COMMON_CFLAGS)
> +datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> +# For date.mod
> +date_mod_SOURCES = commands/date.c
> +date_mod_CFLAGS = $(COMMON_CFLAGS)
> +date_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> include $(srcdir)/conf/common.mk
> diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
> index c1e4ac4..f9c6b4f 100644
> --- a/conf/i386-pc.rmk
> +++ b/conf/i386-pc.rmk
> @@ -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 datetime.mod date.mod
>
> # For biosdisk.mod.
> biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
> @@ -340,4 +340,14 @@ pxecmd_mod_SOURCES = commands/i386/pc/pxecmd.c
> pxecmd_mod_CFLAGS = $(COMMON_CFLAGS)
> pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS)
>
> +# For datetime.mod
> +datetime_mod_SOURCES = commands/datetime.c kern/i386/datetime.c
> +datetime_mod_CFLAGS = $(COMMON_CFLAGS)
> +datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> +# For date.mod
> +date_mod_SOURCES = commands/date.c
> +date_mod_CFLAGS = $(COMMON_CFLAGS)
> +date_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> include $(srcdir)/conf/common.mk
> diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
> index 4f8abba..4fdfa9a 100644
> --- a/conf/x86_64-efi.rmk
> +++ b/conf/x86_64-efi.rmk
> @@ -77,7 +77,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
>
> # Modules.
> pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
> - cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod
> + cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod \
> + datetime.mod date.mod
>
> # For kernel.mod.
> kernel_mod_EXPORTS = no
> @@ -169,4 +170,14 @@ lspci_mod_SOURCES = commands/lspci.c
> lspci_mod_CFLAGS = $(COMMON_CFLAGS)
> lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
>
> +# For datetime.mod
> +datetime_mod_SOURCES = commands/datetime.c kern/efi/datetime.c
> +datetime_mod_CFLAGS = $(COMMON_CFLAGS)
> +datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> +# For date.mod
> +date_mod_SOURCES = commands/date.c
> +date_mod_CFLAGS = $(COMMON_CFLAGS)
> +date_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> include $(srcdir)/conf/common.mk
> diff --git a/include/grub/datetime.h b/include/grub/datetime.h
> new file mode 100644
> index 0000000..3fb5e50
> --- /dev/null
> +++ b/include/grub/datetime.h
> @@ -0,0 +1,58 @@
> +/*
> + * 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 <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef KERNEL_DATETIME_HEADER
> +#define KERNEL_DATETIME_HEADER 1
> +
> +#include <grub/types.h>
> +#include <grub/err.h>
> +
> +#define GRUB_DATETIME_SET_YEAR 1
> +#define GRUB_DATETIME_SET_MONTH 2
> +#define GRUB_DATETIME_SET_DAY 4
> +#define GRUB_DATETIME_SET_DATE (GRUB_DATETIME_SET_YEAR | \
> + GRUB_DATETIME_SET_MONTH | \
> + GRUB_DATETIME_SET_DAY)
> +
> +#define GRUB_DATETIME_SET_HOUR 8
> +#define GRUB_DATETIME_SET_MINUTE 16
> +#define GRUB_DATETIME_SET_SECOND 32
> +#define GRUB_DATETIME_SET_TIME (GRUB_DATETIME_SET_HOUR | \
> + GRUB_DATETIME_SET_MINUTE | \
> + GRUB_DATETIME_SET_SECOND)
> +
> +struct grub_datetime
> +{
> + grub_uint16_t year;
> + grub_uint8_t month;
> + grub_uint8_t day;
> + grub_uint8_t hour;
> + grub_uint8_t minute;
> + grub_uint8_t second;
> +};
> +
> +/* Return date and time. */
> +grub_err_t grub_get_datetime (struct grub_datetime *datetime);
> +
> +/* Set date and time. */
> +grub_err_t grub_set_datetime (struct grub_datetime *datetime, int mask);
> +
> +int grub_get_weekday (struct grub_datetime *datetime);
> +char *grub_get_weekday_name (struct grub_datetime *datetime);
> +
> +#endif /* ! KERNEL_DATETIME_HEADER */
> diff --git a/include/grub/i386/cmos.h b/include/grub/i386/cmos.h
> new file mode 100644
> index 0000000..d482a7d
> --- /dev/null
> +++ b/include/grub/i386/cmos.h
> @@ -0,0 +1,74 @@
> +/*
> + * 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 <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef GRUB_CPU_CMOS_H
> +#define GRUB_CPU_CMOS_H 1
> +
> +#include <grub/types.h>
> +#include <grub/i386/io.h>
> +
> +#define GRUB_CMOS_ADDR_REG 0x70
> +#define GRUB_CMOS_DATA_REG 0x71
> +
> +#define GRUB_CMOS_INDEX_SECOND 0
> +#define GRUB_CMOS_INDEX_SECOND_ALARM 1
> +#define GRUB_CMOS_INDEX_MINUTE 2
> +#define GRUB_CMOS_INDEX_MINUTE_ALARM 3
> +#define GRUB_CMOS_INDEX_HOUR 4
> +#define GRUB_CMOS_INDEX_HOUR_ALARM 5
> +#define GRUB_CMOS_INDEX_DAY_OF_WEEK 6
> +#define GRUB_CMOS_INDEX_DAY_OF_MONTH 7
> +#define GRUB_CMOS_INDEX_MONTH 8
> +#define GRUB_CMOS_INDEX_YEAR 9
> +
> +#define GRUB_CMOS_INDEX_STATUS_A 0xA
> +#define GRUB_CMOS_INDEX_STATUS_B 0xB
> +#define GRUB_CMOS_INDEX_STATUS_C 0xC
> +#define GRUB_CMOS_INDEX_STATUS_D 0xD
> +
> +#define GRUB_CMOS_STATUS_B_DAYLIGHT 1
> +#define GRUB_CMOS_STATUS_B_24HOUR 2
> +#define GRUB_CMOS_STATUS_B_BINARY 4
> +
> +static inline grub_uint8_t
> +grub_bcd_to_num (grub_uint8_t a)
> +{
> + return ((a >> 4) * 10 + (a & 0xF));
> +}
> +
> +static inline grub_uint8_t
> +grub_num_to_bcd (grub_uint8_t a)
> +{
> + return (((a / 10) << 4) + (a % 10));
> +}
> +
> +static inline grub_uint8_t
> +grub_cmos_read (grub_uint8_t index)
> +{
> + grub_outb (index, GRUB_CMOS_ADDR_REG);
> + return grub_inb (GRUB_CMOS_DATA_REG);
> +}
> +
> +static inline void
> +grub_cmos_write (grub_uint8_t index, grub_uint8_t value)
> +{
> + grub_outb (index, GRUB_CMOS_ADDR_REG);
> + grub_outb (value, GRUB_CMOS_DATA_REG);
> +}
> +
> +#endif /* GRUB_CPU_PCI_H */
PCI? :-)
> diff --git a/kern/efi/datetime.c b/kern/efi/datetime.c
> new file mode 100644
> index 0000000..4ba38be
> --- /dev/null
> +++ b/kern/efi/datetime.c
> @@ -0,0 +1,87 @@
> +/* kern/efi/datetime.c - efi datetime function.
> + *
> + * 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 <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/types.h>
> +#include <grub/symbol.h>
> +#include <grub/efi/api.h>
> +#include <grub/efi/efi.h>
> +#include <grub/datetime.h>
> +
> +grub_err_t
> +grub_get_datetime (struct grub_datetime *datetime)
> +{
> + grub_efi_status_t status;
> + struct grub_efi_time efi_time;
> +
> + status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
> + &efi_time, 0);
> +
> + if (status)
> + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t get datetime");
You implemented the function here!
> + else
> + {
> + datetime->year = efi_time.year;
> + datetime->month = efi_time.month;
> + datetime->day = efi_time.day;
> + datetime->hour = efi_time.hour;
> + datetime->minute = efi_time.minute;
> + datetime->second = efi_time.second;
> + }
> +
> + return 0;
> +}
> +
> +grub_err_t
> +grub_set_datetime (struct grub_datetime *datetime, int mask)
> +{
> + grub_efi_status_t status;
> + struct grub_efi_time efi_time;
Why do you use a mask? Isn't it better to let the caller to deal with
this by calling grub_get_datetime? Perhaps I do not see the results
of dealing with this either way.
> + status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
> + &efi_time, 0);
> +
> + if (status)
> + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t get datetime");
> +
> + if (mask & GRUB_DATETIME_SET_YEAR)
> + efi_time.year = datetime->year;
> +
> + if (mask & GRUB_DATETIME_SET_MONTH)
> + efi_time.month = datetime->month;
> +
> + if (mask & GRUB_DATETIME_SET_DAY)
> + efi_time.day = datetime->day;
> +
> + if (mask & GRUB_DATETIME_SET_HOUR)
> + efi_time.hour = datetime->hour;
> +
> + if (mask & GRUB_DATETIME_SET_MINUTE)
> + efi_time.minute = datetime->minute;
> +
> + if (mask & GRUB_DATETIME_SET_SECOND)
> + efi_time.second = datetime->second;
> +
> + status = efi_call_1 (grub_efi_system_table->runtime_services->set_time,
> + &efi_time);
> +
> + if (status)
> + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t set datetime");
> +
> + return 0;
> +}
> diff --git a/kern/i386/datetime.c b/kern/i386/datetime.c
> new file mode 100644
> index 0000000..466a404
> --- /dev/null
> +++ b/kern/i386/datetime.c
> @@ -0,0 +1,175 @@
> +/* kern/i386/datetime.c - x86 CMOS datetime function.
> + *
> + * 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 <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/datetime.h>
> +#include <grub/i386/cmos.h>
> +
> +grub_err_t
> +grub_get_datetime (struct grub_datetime *datetime)
> +{
> + int is_bcd, is_12hour;
> + grub_uint8_t value, flag;
> +
> + flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
> +
> + is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
> +
> + value = grub_cmos_read (GRUB_CMOS_INDEX_YEAR);
> + if (is_bcd)
> + value = grub_bcd_to_num (value);
> +
> + datetime->year = value;
> + datetime->year += (value < 80) ? 2000 : 1900;
> +
> + value = grub_cmos_read (GRUB_CMOS_INDEX_MONTH);
> + if (is_bcd)
> + value = grub_bcd_to_num (value);
> +
> + datetime->month = value;
> +
> + value = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH);
> + if (is_bcd)
> + value = grub_bcd_to_num (value);
> +
> + datetime->day = value;
> +
> + is_12hour = ! (flag & GRUB_CMOS_STATUS_B_24HOUR);
> +
> + value = grub_cmos_read (GRUB_CMOS_INDEX_HOUR);
> + if (is_12hour)
> + {
> + is_12hour = (value & 0x80);
> +
> + value &= 0x7F;
> + value--;
> + }
> +
> + if (is_bcd)
> + value = grub_bcd_to_num (value);
> +
> + if (is_12hour)
> + value += 12;
> +
> + datetime->hour = value;
> +
> + value = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE);
> + if (is_bcd)
> + value = grub_bcd_to_num (value);
> +
> + datetime->minute = value;
> +
> + value = grub_cmos_read (GRUB_CMOS_INDEX_SECOND);
> + if (is_bcd)
> + value = grub_bcd_to_num (value);
> +
> + datetime->second = value;
> +
> + return 0;
> +}
> +
> +grub_err_t
> +grub_set_datetime (struct grub_datetime *datetime, int mask)
> +{
> + int is_bcd;
> + grub_uint8_t value, flag;
> +
> + flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
> +
> + is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
> +
> + if (mask & GRUB_DATETIME_SET_YEAR)
> + {
> + value = ((datetime->year >= 2000) ? datetime->year - 2000 :
> + datetime->year - 1900);
> +
> + if (is_bcd)
> + value = grub_num_to_bcd (value);
> +
> + grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value);
> + }
> +
> + if (mask & GRUB_DATETIME_SET_MONTH)
> + {
> + value = datetime->month;
> +
> + if (is_bcd)
> + value = grub_num_to_bcd (value);
> +
> + grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value);
> + }
> +
> + if (mask & GRUB_DATETIME_SET_DAY)
> + {
> + value = datetime->day;
> +
> + if (is_bcd)
> + value = grub_num_to_bcd (value);
> +
> + grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value);
> + }
> +
> + if (mask & GRUB_DATETIME_SET_HOUR)
> + {
> + int is_12hour;
> +
> + value = datetime->hour;
> +
> + is_12hour = (! (flag & GRUB_CMOS_STATUS_B_24HOUR));
> +
> + if (is_12hour)
> + {
> + value++;
> +
> + if (value > 12)
> + value -= 12;
> + else
> + is_12hour = 0;
> + }
> +
> + if (is_bcd)
> + value = grub_num_to_bcd (value);
> +
> + if (is_12hour)
> + value |= 0x80;
> +
> + grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value);
> + }
> +
> + if (mask & GRUB_DATETIME_SET_MINUTE)
> + {
> + value = datetime->minute;
> +
> + if (is_bcd)
> + value = grub_num_to_bcd (value);
> +
> + grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value);
> + }
> +
> + if (mask & GRUB_DATETIME_SET_SECOND)
> + {
> + value = datetime->second;
> +
> + if (is_bcd)
> + value = grub_num_to_bcd (value);
> +
> + grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value);
> + }
> +
> + return 0;
> +}
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-11 21:07 ` Marco Gerards
@ 2008-08-12 17:13 ` Bean
2008-08-12 21:49 ` Marco Gerards
0 siblings, 1 reply; 28+ messages in thread
From: Bean @ 2008-08-12 17:13 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 3799 bytes --]
On Tue, Aug 12, 2008 at 5:07 AM, Marco Gerards <mgerards@xs4all.nl> wrote:
>
>> * commands/date.c: New file.
>>
>> * commands/datetime.c: Likewise.
>
> This is not a command. But I do not really know a good place for this
> module...
How about the /hook directory ?
>
>> * include/grub/datetime.h: Likewise.
>>
>> * include/grub/i386/cmos.h: Likewise.
>>
>> * kern/i386/datetime.c: Likewise.
>>
>> * kern/efi/datetime.c: Likewise.
>
> Does this really belong in the kernel? You created lib/ (which I
> still not might agree with, but ok ;)). But that might be a better
> place than here.
Ok.
>> + "Sunday",
>> + "Monday",
>> + "Tueday",
>
> Tuesday
>
>> + "Wednesday",
>> + "Thusday",
>
> Thursday
Oh, fixed.
>> +int
>> +grub_get_weekday (struct grub_datetime *datetime)
>> +{
>> + int a, y, m;
>> +
>> + a = (14 - datetime->month) / 12;
>> + y = datetime->year - a;
>> + m = datetime->month + 12 * a - 2;
>> +
>> + return (datetime->day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7;
>
> Wow ;-)
>
> Does this deal with leap years?
It should be able to handle leap years.
>> +GRUB_MOD_FINI(datetime)
>> +{
>> + int i;
>> +
>> + for (i = 0; i < 7; i++)
>> + grub_register_variable_hook (grub_datetime_names[i], 0, 0);
>
> Perhaps it is even wise to unset the variables? As the contents are
> no longer valid.
Right, fixed.
>> +grub_err_t
>> +grub_get_datetime (struct grub_datetime *datetime)
>> +{
>> + grub_efi_status_t status;
>> + struct grub_efi_time efi_time;
>> +
>> + status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
>> + &efi_time, 0);
>> +
>> + if (status)
>> + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "can\'t get datetime");
>
> You implemented the function here!
Ok, change the error code.
>> +grub_err_t
>> +grub_set_datetime (struct grub_datetime *datetime, int mask)
>> +{
>> + grub_efi_status_t status;
>> + struct grub_efi_time efi_time;
>
> Why do you use a mask? Isn't it better to let the caller to deal with
> this by calling grub_get_datetime? Perhaps I do not see the results
> of dealing with this either way.
Ok then.
2008-08-12 Bean <bean123ch@gmail.com>
* conf/i386-pc.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
* conf/i386-coreboot.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
* conf/i386-ieee1275.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
* conf/i386-efi.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
* conf/x86_64-efi.rmk (pkglib_MODULES): Add datetime.mod and date.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
* commands/date.c: New file.
* hook/datetime.c: Likewise.
* include/grub/lib/datetime.h: Likewise.
* include/grub/i386/cmos.h: Likewise.
* lib/i386/datetime.c: Likewise.
* lib/efi/datetime.c: Likewise.
--
Bean
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: date_4.diff --]
[-- Type: text/x-diff; name=date_4.diff, Size: 22578 bytes --]
diff --git a/commands/date.c b/commands/date.c
new file mode 100644
index 0000000..2331918
--- /dev/null
+++ b/commands/date.c
@@ -0,0 +1,145 @@
+/* date.c - command to display/set current datetime. */
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/lib/datetime.h>
+
+#define GRUB_DATETIME_SET_YEAR 1
+#define GRUB_DATETIME_SET_MONTH 2
+#define GRUB_DATETIME_SET_DAY 4
+#define GRUB_DATETIME_SET_HOUR 8
+#define GRUB_DATETIME_SET_MINUTE 16
+#define GRUB_DATETIME_SET_SECOND 32
+
+static grub_err_t
+grub_cmd_date (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_datetime datetime;
+ int limit[6][2] = {{1980, 2079}, {1, 12}, {1, 31}, {0, 23}, {0, 59}, {0, 59}};
+ int value[6], mask;
+
+ if (argc == 0)
+ {
+ if (grub_get_datetime (&datetime))
+ return grub_errno;
+
+ grub_printf ("%d-%02d-%02d %02d:%02d:%02d %s\n",
+ datetime.year, datetime.month, datetime.day,
+ datetime.hour, datetime.minute, datetime.second,
+ grub_get_weekday_name (&datetime));
+
+ return 0;
+ }
+
+ grub_memset (&value, 0, sizeof (value));
+ mask = 0;
+
+ for (; argc; argc--, args++)
+ {
+ char *p, c;
+ int m1, ofs, n, cur_mask;
+
+ p = args[0];
+ m1 = grub_strtoul (p, &p, 10);
+
+ c = *p;
+ if (c == '-')
+ ofs = 0;
+ else if (c == ':')
+ ofs = 3;
+ else
+ goto fail;
+
+ value[ofs] = m1;
+ cur_mask = (1 << ofs);
+ mask &= ~(cur_mask * (1 + 2 + 4));
+
+ for (n = 1; (n < 3) && (*p); n++)
+ {
+ if (*p != c)
+ goto fail;
+
+ value[ofs + n] = grub_strtoul (p + 1, &p, 10);
+ cur_mask |= (1 << (ofs + n));
+ }
+
+ if (*p)
+ goto fail;
+
+ if ((ofs == 0) && (n == 2))
+ {
+ value[ofs + 2] = value[ofs + 1];
+ value[ofs + 1] = value[ofs];
+ ofs++;
+ cur_mask <<= 1;
+ }
+
+ for (; n; n--, ofs++)
+ if ((value [ofs] < limit[ofs][0]) ||
+ (value [ofs] > limit[ofs][1]))
+ goto fail;
+
+ mask |= cur_mask;
+ }
+
+ if (grub_get_datetime (&datetime))
+ return grub_errno;
+
+ if (mask & GRUB_DATETIME_SET_YEAR)
+ datetime.year = value[0];
+
+ if (mask & GRUB_DATETIME_SET_MONTH)
+ datetime.month = value[1];
+
+ if (mask & GRUB_DATETIME_SET_DAY)
+ datetime.day = value[2];
+
+ if (mask & GRUB_DATETIME_SET_HOUR)
+ datetime.hour = value[3];
+
+ if (mask & GRUB_DATETIME_SET_MINUTE)
+ datetime.minute = value[4];
+
+ if (mask & GRUB_DATETIME_SET_SECOND)
+ datetime.second = value[5];
+
+ return grub_set_datetime (&datetime);
+
+fail:
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid datetime");
+}
+
+GRUB_MOD_INIT(date)
+{
+ (void) mod; /* To stop warning. */
+ grub_register_command ("date", grub_cmd_date,
+ GRUB_COMMAND_FLAG_BOTH,
+ "date [[year-]month-day] [hour:minute[:second]]",
+ "Command to display/set current datetime.", 0);
+}
+
+GRUB_MOD_FINI(date)
+{
+ grub_unregister_command ("date");
+}
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index 606b99c..8bd92b9 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -102,7 +102,7 @@ pkglib_MODULES = _linux.mod linux.mod normal.mod \
_multiboot.mod multiboot.mod aout.mod \
play.mod cpuid.mod serial.mod ata.mod \
memdisk.mod pci.mod lspci.mod reboot.mod \
- halt.mod
+ halt.mod datetime.mod date.mod
# For _linux.mod.
_linux_mod_SOURCES = loader/i386/pc/linux.c
@@ -187,4 +187,14 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = hook/datetime.c lib/i386/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 2ce21b1..5126927 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -75,7 +75,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
- _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod
+ _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod \
+ datetime.mod date.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -167,4 +168,14 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = hook/datetime.c lib/efi/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index a93845e..8ea12f5 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -104,7 +104,8 @@ grub_install_SOURCES = util/ieee1275/grub-install.in
# Modules.
pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod cpuid.mod \
multiboot.mod _multiboot.mod aout.mod serial.mod linux.mod \
- _linux.mod nand.mod memdisk.mod pci.mod lspci.mod
+ _linux.mod nand.mod memdisk.mod pci.mod lspci.mod datetime.mod \
+ date.mod
# For normal.mod.
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
@@ -188,4 +189,14 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = hook/datetime.c lib/i386/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index c1e4ac4..00f94ea 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -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 datetime.mod date.mod
# For biosdisk.mod.
biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -340,4 +340,14 @@ pxecmd_mod_SOURCES = commands/i386/pc/pxecmd.c
pxecmd_mod_CFLAGS = $(COMMON_CFLAGS)
pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = hook/datetime.c lib/i386/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
index 4f8abba..9421c65 100644
--- a/conf/x86_64-efi.rmk
+++ b/conf/x86_64-efi.rmk
@@ -77,7 +77,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
- cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod
+ cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod \
+ datetime.mod date.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -169,4 +170,14 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = hook/datetime.c lib/efi/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/hook/datetime.c b/hook/datetime.c
new file mode 100644
index 0000000..c43a692
--- /dev/null
+++ b/hook/datetime.c
@@ -0,0 +1,135 @@
+/* datetime.c - Module to export datetime variables. */
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/lib/datetime.h>
+
+static char *grub_weekday_names[] =
+{
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+};
+
+static char *grub_datetime_names[] =
+{
+ "YEAR",
+ "MONTH",
+ "DAY",
+ "HOUR",
+ "MINUTE",
+ "SECOND",
+ "WEEKDAY",
+};
+
+int
+grub_get_weekday (struct grub_datetime *datetime)
+{
+ int a, y, m;
+
+ a = (14 - datetime->month) / 12;
+ y = datetime->year - a;
+ m = datetime->month + 12 * a - 2;
+
+ return (datetime->day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7;
+}
+
+char *
+grub_get_weekday_name (struct grub_datetime *datetime)
+{
+ return grub_weekday_names[grub_get_weekday (datetime)];
+}
+
+static char *
+grub_read_hook_datetime (struct grub_env_var *var,
+ const char *val __attribute__ ((unused)))
+{
+ struct grub_datetime datetime;
+ static char buf[6];
+
+ buf[0] = 0;
+ if (! grub_get_datetime (&datetime))
+ {
+ int i;
+
+ for (i = 0; i < 7; i++)
+ if (! grub_strcmp (var->name, grub_datetime_names[i]))
+ {
+ int n;
+
+ switch (i)
+ {
+ case 0:
+ n = datetime.year;
+ break;
+ case 1:
+ n = datetime.month;
+ break;
+ case 2:
+ n = datetime.day;
+ break;
+ case 3:
+ n = datetime.hour;
+ break;
+ case 4:
+ n = datetime.minute;
+ break;
+ case 5:
+ n = datetime.second;
+ break;
+ default:
+ return grub_get_weekday_name (&datetime);
+ }
+
+ grub_sprintf (buf, "%d", n);
+ break;
+ }
+ }
+
+ return buf;
+}
+
+GRUB_MOD_INIT(datetime)
+{
+ (void)mod; /* To stop warning. */
+ int i;
+
+ for (i = 0; i < 7; i++)
+ grub_register_variable_hook (grub_datetime_names[i],
+ grub_read_hook_datetime, 0);
+}
+
+GRUB_MOD_FINI(datetime)
+{
+ int i;
+
+ for (i = 0; i < 7; i++)
+ {
+ grub_register_variable_hook (grub_datetime_names[i], 0, 0);
+ grub_env_unset (grub_datetime_names[i]);
+ }
+}
diff --git a/include/grub/i386/cmos.h b/include/grub/i386/cmos.h
new file mode 100644
index 0000000..1c0530d
--- /dev/null
+++ b/include/grub/i386/cmos.h
@@ -0,0 +1,74 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CPU_CMOS_H
+#define GRUB_CPU_CMOS_H 1
+
+#include <grub/types.h>
+#include <grub/i386/io.h>
+
+#define GRUB_CMOS_ADDR_REG 0x70
+#define GRUB_CMOS_DATA_REG 0x71
+
+#define GRUB_CMOS_INDEX_SECOND 0
+#define GRUB_CMOS_INDEX_SECOND_ALARM 1
+#define GRUB_CMOS_INDEX_MINUTE 2
+#define GRUB_CMOS_INDEX_MINUTE_ALARM 3
+#define GRUB_CMOS_INDEX_HOUR 4
+#define GRUB_CMOS_INDEX_HOUR_ALARM 5
+#define GRUB_CMOS_INDEX_DAY_OF_WEEK 6
+#define GRUB_CMOS_INDEX_DAY_OF_MONTH 7
+#define GRUB_CMOS_INDEX_MONTH 8
+#define GRUB_CMOS_INDEX_YEAR 9
+
+#define GRUB_CMOS_INDEX_STATUS_A 0xA
+#define GRUB_CMOS_INDEX_STATUS_B 0xB
+#define GRUB_CMOS_INDEX_STATUS_C 0xC
+#define GRUB_CMOS_INDEX_STATUS_D 0xD
+
+#define GRUB_CMOS_STATUS_B_DAYLIGHT 1
+#define GRUB_CMOS_STATUS_B_24HOUR 2
+#define GRUB_CMOS_STATUS_B_BINARY 4
+
+static inline grub_uint8_t
+grub_bcd_to_num (grub_uint8_t a)
+{
+ return ((a >> 4) * 10 + (a & 0xF));
+}
+
+static inline grub_uint8_t
+grub_num_to_bcd (grub_uint8_t a)
+{
+ return (((a / 10) << 4) + (a % 10));
+}
+
+static inline grub_uint8_t
+grub_cmos_read (grub_uint8_t index)
+{
+ grub_outb (index, GRUB_CMOS_ADDR_REG);
+ return grub_inb (GRUB_CMOS_DATA_REG);
+}
+
+static inline void
+grub_cmos_write (grub_uint8_t index, grub_uint8_t value)
+{
+ grub_outb (index, GRUB_CMOS_ADDR_REG);
+ grub_outb (value, GRUB_CMOS_DATA_REG);
+}
+
+#endif /* GRUB_CPU_CMOS_H */
diff --git a/include/grub/lib/datetime.h b/include/grub/lib/datetime.h
new file mode 100644
index 0000000..7b140cc
--- /dev/null
+++ b/include/grub/lib/datetime.h
@@ -0,0 +1,44 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_DATETIME_HEADER
+#define KERNEL_DATETIME_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+
+struct grub_datetime
+{
+ grub_uint16_t year;
+ grub_uint8_t month;
+ grub_uint8_t day;
+ grub_uint8_t hour;
+ grub_uint8_t minute;
+ grub_uint8_t second;
+};
+
+/* Return date and time. */
+grub_err_t grub_get_datetime (struct grub_datetime *datetime);
+
+/* Set date and time. */
+grub_err_t grub_set_datetime (struct grub_datetime *datetime);
+
+int grub_get_weekday (struct grub_datetime *datetime);
+char *grub_get_weekday_name (struct grub_datetime *datetime);
+
+#endif /* ! KERNEL_DATETIME_HEADER */
diff --git a/lib/efi/datetime.c b/lib/efi/datetime.c
new file mode 100644
index 0000000..9fa72fd
--- /dev/null
+++ b/lib/efi/datetime.c
@@ -0,0 +1,79 @@
+/* kern/efi/datetime.c - efi datetime function.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/lib/datetime.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+ grub_efi_status_t status;
+ struct grub_efi_time efi_time;
+
+ status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
+ &efi_time, 0);
+
+ if (status)
+ return grub_error (GRUB_ERR_INVALID_COMMAND,
+ "can\'t get datetime using efi");
+ else
+ {
+ datetime->year = efi_time.year;
+ datetime->month = efi_time.month;
+ datetime->day = efi_time.day;
+ datetime->hour = efi_time.hour;
+ datetime->minute = efi_time.minute;
+ datetime->second = efi_time.second;
+ }
+
+ return 0;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime)
+{
+ grub_efi_status_t status;
+ struct grub_efi_time efi_time;
+
+ status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
+ &efi_time, 0);
+
+ if (status)
+ return grub_error (GRUB_ERR_INVALID_COMMAND,
+ "can\'t get datetime using efi");
+
+ efi_time.year = datetime->year;
+ efi_time.month = datetime->month;
+ efi_time.day = datetime->day;
+ efi_time.hour = datetime->hour;
+ efi_time.minute = datetime->minute;
+ efi_time.second = datetime->second;
+
+ status = efi_call_1 (grub_efi_system_table->runtime_services->set_time,
+ &efi_time);
+
+ if (status)
+ return grub_error (GRUB_ERR_INVALID_COMMAND,
+ "can\'t set datetime using efi");
+
+ return 0;
+}
diff --git a/lib/i386/datetime.c b/lib/i386/datetime.c
new file mode 100644
index 0000000..1e59746
--- /dev/null
+++ b/lib/i386/datetime.c
@@ -0,0 +1,155 @@
+/* kern/i386/datetime.c - x86 CMOS datetime function.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/lib/datetime.h>
+#include <grub/i386/cmos.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+ int is_bcd, is_12hour;
+ grub_uint8_t value, flag;
+
+ flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+
+ is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_YEAR);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->year = value;
+ datetime->year += (value < 80) ? 2000 : 1900;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->month = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->day = value;
+
+ is_12hour = ! (flag & GRUB_CMOS_STATUS_B_24HOUR);
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_HOUR);
+ if (is_12hour)
+ {
+ is_12hour = (value & 0x80);
+
+ value &= 0x7F;
+ value--;
+ }
+
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ if (is_12hour)
+ value += 12;
+
+ datetime->hour = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->minute = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_SECOND);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->second = value;
+
+ return 0;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime)
+{
+ int is_bcd, is_12hour;
+ grub_uint8_t value, flag;
+
+ flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+
+ is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
+
+ value = ((datetime->year >= 2000) ? datetime->year - 2000 :
+ datetime->year - 1900);
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value);
+
+ value = datetime->month;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value);
+
+ value = datetime->day;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value);
+
+ value = datetime->hour;
+
+ is_12hour = (! (flag & GRUB_CMOS_STATUS_B_24HOUR));
+
+ if (is_12hour)
+ {
+ value++;
+
+ if (value > 12)
+ value -= 12;
+ else
+ is_12hour = 0;
+ }
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ if (is_12hour)
+ value |= 0x80;
+
+ grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value);
+
+ value = datetime->minute;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value);
+
+ value = datetime->second;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value);
+
+ return 0;
+}
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-12 17:13 ` Bean
@ 2008-08-12 21:49 ` Marco Gerards
2008-08-13 1:46 ` Bean
0 siblings, 1 reply; 28+ messages in thread
From: Marco Gerards @ 2008-08-12 21:49 UTC (permalink / raw)
To: The development of GRUB 2
Bean <bean123ch@gmail.com> writes:
> On Tue, Aug 12, 2008 at 5:07 AM, Marco Gerards <mgerards@xs4all.nl> wrote:
>>
>>> * commands/date.c: New file.
>>>
>>> * commands/datetime.c: Likewise.
>>
>> This is not a command. But I do not really know a good place for this
>> module...
>
> How about the /hook directory ?
Perhaps? Do you have suggestions what we can place there, besides
this?
Otherwise the patch looks fine to me :-)
--
Marco
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-12 21:49 ` Marco Gerards
@ 2008-08-13 1:46 ` Bean
2008-08-13 3:26 ` Bean
2008-08-13 10:17 ` Marco Gerards
0 siblings, 2 replies; 28+ messages in thread
From: Bean @ 2008-08-13 1:46 UTC (permalink / raw)
To: The development of GRUB 2
On Wed, Aug 13, 2008 at 5:49 AM, Marco Gerards <mgerards@xs4all.nl> wrote:
> Bean <bean123ch@gmail.com> writes:
>
>> On Tue, Aug 12, 2008 at 5:07 AM, Marco Gerards <mgerards@xs4all.nl> wrote:
>>>
>>>> * commands/date.c: New file.
>>>>
>>>> * commands/datetime.c: Likewise.
>>>
>>> This is not a command. But I do not really know a good place for this
>>> module...
>>
>> How about the /hook directory ?
>
> Perhaps? Do you have suggestions what we can place there, besides
> this?
>
> Otherwise the patch looks fine to me :-)
Hi,
Oh, please take a look at my other post "Idea: implementation of the
password command", it sugguest to implement password with hooks, for
example, reading $GET_PASSWORD would prompt the user for password and
return the encrypted form.
BTW, I'm thinking perhaps it's better to move the hook function from
datetime.mod to datehook.mod, and datetime.mod only contain
grub_get_datetime, grub_set_datetime, grub_get_weekday and
grub_get_weekday_name. Module like date.mod only need the datetime
functions, it's a little wired to install the hook as a side effect.
--
Bean
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-13 1:46 ` Bean
@ 2008-08-13 3:26 ` Bean
2008-08-13 10:17 ` Marco Gerards
1 sibling, 0 replies; 28+ messages in thread
From: Bean @ 2008-08-13 3:26 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 4363 bytes --]
On Wed, Aug 13, 2008 at 9:46 AM, Bean <bean123ch@gmail.com> wrote:
> On Wed, Aug 13, 2008 at 5:49 AM, Marco Gerards <mgerards@xs4all.nl> wrote:
>> Bean <bean123ch@gmail.com> writes:
>>
>>> On Tue, Aug 12, 2008 at 5:07 AM, Marco Gerards <mgerards@xs4all.nl> wrote:
>>>>
>>>>> * commands/date.c: New file.
>>>>>
>>>>> * commands/datetime.c: Likewise.
>>>>
>>>> This is not a command. But I do not really know a good place for this
>>>> module...
>>>
>>> How about the /hook directory ?
>>
>> Perhaps? Do you have suggestions what we can place there, besides
>> this?
>>
>> Otherwise the patch looks fine to me :-)
>
> Hi,
>
> Oh, please take a look at my other post "Idea: implementation of the
> password command", it sugguest to implement password with hooks, for
> example, reading $GET_PASSWORD would prompt the user for password and
> return the encrypted form.
>
> BTW, I'm thinking perhaps it's better to move the hook function from
> datetime.mod to datehook.mod, and datetime.mod only contain
> grub_get_datetime, grub_set_datetime, grub_get_weekday and
> grub_get_weekday_name. Module like date.mod only need the datetime
> functions, it's a little wired to install the hook as a side effect.
Hi,
This is the new patch. BTW. when testing datehook.mod, I found a
serious bug in grub_env_insert:
static void
grub_env_insert (struct grub_env_context *context,
struct grub_env_var *var)
{
int idx = grub_env_hashval (var->name);
/* Insert the variable into the hashtable. */
var->prevp = &context->vars[idx];
var->next = context->vars[idx];
if (var->next)
- var->next->prevp = &var;
+ var->next->prevp = &(var->next);
context->vars[idx] = var;
}
prevp should point to the variable that points to the next item, so it
should be &(var->next) instead of &var. To see the effect, you can
insmod datehook then rmmod datehook. The old code would either hang,
or you can see some of the datetime variable, like $YEAR, still
present in the variable list. If you try to unset it, it will cause
allocate magic broken error.
2008-08-11 Bean <bean123ch@gmail.com>
* conf/i386-pc.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and datehook.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(datehook_mod_SOURCES): Likewise.
(datehook_mod_CFLAGS): Likewise.
(datehook_mod_LDFLAGS): Likewise.
* conf/i386-coreboot.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and datehook.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(datehook_mod_SOURCES): Likewise.
(datehook_mod_CFLAGS): Likewise.
(datehook_mod_LDFLAGS): Likewise.
* conf/i386-ieee1275.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and datehook.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(datehook_mod_SOURCES): Likewise.
(datehook_mod_CFLAGS): Likewise.
(datehook_mod_LDFLAGS): Likewise.
* conf/i386-efi.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and datehook.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(datehook_mod_SOURCES): Likewise.
(datehook_mod_CFLAGS): Likewise.
(datehook_mod_LDFLAGS): Likewise.
* conf/x86_64-efi.rmk (pkglib_MODULES): Add datetime.mod, date.mod
and datehook.mod.
(datetime_mod_SOURCES): New macro.
(datetime_mod_CFLAGS): Likewise.
(datetime_mod_LDFLAGS): Likewise.
(date_mod_SOURCES): Likewise.
(date_mod_CFLAGS): Likewise.
(date_mod_LDFLAGS): Likewise.
(datehook_mod_SOURCES): Likewise.
(datehook_mod_CFLAGS): Likewise.
(datehook_mod_LDFLAGS): Likewise.
* kern/env.c (grub_env_insert): Fix a bug in prevp pointer.
* commands/date.c: New file.
* hook/datetime.c: Likewise.
* include/grub/lib/datetime.h: Likewise.
* include/grub/i386/cmos.h: Likewise.
* lib/datetime.c: Likewise.
* lib/i386/datetime.c: Likewise.
* lib/efi/datetime.c: Likewise.
--
Bean
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: date_5.diff --]
[-- Type: text/x-diff; name=date_5.diff, Size: 24844 bytes --]
diff --git a/commands/date.c b/commands/date.c
new file mode 100644
index 0000000..2331918
--- /dev/null
+++ b/commands/date.c
@@ -0,0 +1,145 @@
+/* date.c - command to display/set current datetime. */
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/lib/datetime.h>
+
+#define GRUB_DATETIME_SET_YEAR 1
+#define GRUB_DATETIME_SET_MONTH 2
+#define GRUB_DATETIME_SET_DAY 4
+#define GRUB_DATETIME_SET_HOUR 8
+#define GRUB_DATETIME_SET_MINUTE 16
+#define GRUB_DATETIME_SET_SECOND 32
+
+static grub_err_t
+grub_cmd_date (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ struct grub_datetime datetime;
+ int limit[6][2] = {{1980, 2079}, {1, 12}, {1, 31}, {0, 23}, {0, 59}, {0, 59}};
+ int value[6], mask;
+
+ if (argc == 0)
+ {
+ if (grub_get_datetime (&datetime))
+ return grub_errno;
+
+ grub_printf ("%d-%02d-%02d %02d:%02d:%02d %s\n",
+ datetime.year, datetime.month, datetime.day,
+ datetime.hour, datetime.minute, datetime.second,
+ grub_get_weekday_name (&datetime));
+
+ return 0;
+ }
+
+ grub_memset (&value, 0, sizeof (value));
+ mask = 0;
+
+ for (; argc; argc--, args++)
+ {
+ char *p, c;
+ int m1, ofs, n, cur_mask;
+
+ p = args[0];
+ m1 = grub_strtoul (p, &p, 10);
+
+ c = *p;
+ if (c == '-')
+ ofs = 0;
+ else if (c == ':')
+ ofs = 3;
+ else
+ goto fail;
+
+ value[ofs] = m1;
+ cur_mask = (1 << ofs);
+ mask &= ~(cur_mask * (1 + 2 + 4));
+
+ for (n = 1; (n < 3) && (*p); n++)
+ {
+ if (*p != c)
+ goto fail;
+
+ value[ofs + n] = grub_strtoul (p + 1, &p, 10);
+ cur_mask |= (1 << (ofs + n));
+ }
+
+ if (*p)
+ goto fail;
+
+ if ((ofs == 0) && (n == 2))
+ {
+ value[ofs + 2] = value[ofs + 1];
+ value[ofs + 1] = value[ofs];
+ ofs++;
+ cur_mask <<= 1;
+ }
+
+ for (; n; n--, ofs++)
+ if ((value [ofs] < limit[ofs][0]) ||
+ (value [ofs] > limit[ofs][1]))
+ goto fail;
+
+ mask |= cur_mask;
+ }
+
+ if (grub_get_datetime (&datetime))
+ return grub_errno;
+
+ if (mask & GRUB_DATETIME_SET_YEAR)
+ datetime.year = value[0];
+
+ if (mask & GRUB_DATETIME_SET_MONTH)
+ datetime.month = value[1];
+
+ if (mask & GRUB_DATETIME_SET_DAY)
+ datetime.day = value[2];
+
+ if (mask & GRUB_DATETIME_SET_HOUR)
+ datetime.hour = value[3];
+
+ if (mask & GRUB_DATETIME_SET_MINUTE)
+ datetime.minute = value[4];
+
+ if (mask & GRUB_DATETIME_SET_SECOND)
+ datetime.second = value[5];
+
+ return grub_set_datetime (&datetime);
+
+fail:
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid datetime");
+}
+
+GRUB_MOD_INIT(date)
+{
+ (void) mod; /* To stop warning. */
+ grub_register_command ("date", grub_cmd_date,
+ GRUB_COMMAND_FLAG_BOTH,
+ "date [[year-]month-day] [hour:minute[:second]]",
+ "Command to display/set current datetime.", 0);
+}
+
+GRUB_MOD_FINI(date)
+{
+ grub_unregister_command ("date");
+}
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index 606b99c..fada5d2 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -102,7 +102,7 @@ pkglib_MODULES = _linux.mod linux.mod normal.mod \
_multiboot.mod multiboot.mod aout.mod \
play.mod cpuid.mod serial.mod ata.mod \
memdisk.mod pci.mod lspci.mod reboot.mod \
- halt.mod
+ halt.mod datetime.mod date.mod datehook.mod
# For _linux.mod.
_linux_mod_SOURCES = loader/i386/pc/linux.c
@@ -187,4 +187,19 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/i386/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 2ce21b1..ef7d8a2 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -75,7 +75,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
- _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod
+ _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod \
+ datetime.mod date.mod datehook.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -167,4 +168,19 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/efi/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index a93845e..53dd9e5 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -104,7 +104,8 @@ grub_install_SOURCES = util/ieee1275/grub-install.in
# Modules.
pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod cpuid.mod \
multiboot.mod _multiboot.mod aout.mod serial.mod linux.mod \
- _linux.mod nand.mod memdisk.mod pci.mod lspci.mod
+ _linux.mod nand.mod memdisk.mod pci.mod lspci.mod datetime.mod \
+ date.mod datehook.mod
# For normal.mod.
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
@@ -188,4 +189,19 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/i386/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index c1e4ac4..1ad2e73 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -163,7 +163,8 @@ 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 datetime.mod date.mod \
+ datehook.mod
# For biosdisk.mod.
biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -340,4 +341,19 @@ pxecmd_mod_SOURCES = commands/i386/pc/pxecmd.c
pxecmd_mod_CFLAGS = $(COMMON_CFLAGS)
pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/i386/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
index 4f8abba..473c34e 100644
--- a/conf/x86_64-efi.rmk
+++ b/conf/x86_64-efi.rmk
@@ -77,7 +77,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
- cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod
+ cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod \
+ datetime.mod date.mod datehook.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -169,4 +170,19 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/efi/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/hook/datehook.c b/hook/datehook.c
new file mode 100644
index 0000000..9419d48
--- /dev/null
+++ b/hook/datehook.c
@@ -0,0 +1,106 @@
+/* datehook.c - Module to install datetime hooks. */
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/lib/datetime.h>
+
+static char *grub_datetime_names[] =
+{
+ "YEAR",
+ "MONTH",
+ "DAY",
+ "HOUR",
+ "MINUTE",
+ "SECOND",
+ "WEEKDAY",
+};
+
+static char *
+grub_read_hook_datetime (struct grub_env_var *var,
+ const char *val __attribute__ ((unused)))
+{
+ struct grub_datetime datetime;
+ static char buf[6];
+
+ buf[0] = 0;
+ if (! grub_get_datetime (&datetime))
+ {
+ int i;
+
+ for (i = 0; i < 7; i++)
+ if (! grub_strcmp (var->name, grub_datetime_names[i]))
+ {
+ int n;
+
+ switch (i)
+ {
+ case 0:
+ n = datetime.year;
+ break;
+ case 1:
+ n = datetime.month;
+ break;
+ case 2:
+ n = datetime.day;
+ break;
+ case 3:
+ n = datetime.hour;
+ break;
+ case 4:
+ n = datetime.minute;
+ break;
+ case 5:
+ n = datetime.second;
+ break;
+ default:
+ return grub_get_weekday_name (&datetime);
+ }
+
+ grub_sprintf (buf, "%d", n);
+ break;
+ }
+ }
+
+ return buf;
+}
+
+GRUB_MOD_INIT(datetime)
+{
+ (void)mod; /* To stop warning. */
+ int i;
+
+ for (i = 0; i < 7; i++)
+ grub_register_variable_hook (grub_datetime_names[i],
+ grub_read_hook_datetime, 0);
+}
+
+GRUB_MOD_FINI(datetime)
+{
+ int i;
+
+ for (i = 0; i < 7; i++)
+ {
+ grub_register_variable_hook (grub_datetime_names[i], 0, 0);
+ grub_env_unset (grub_datetime_names[i]);
+ }
+}
diff --git a/include/grub/i386/cmos.h b/include/grub/i386/cmos.h
new file mode 100644
index 0000000..1c0530d
--- /dev/null
+++ b/include/grub/i386/cmos.h
@@ -0,0 +1,74 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_CPU_CMOS_H
+#define GRUB_CPU_CMOS_H 1
+
+#include <grub/types.h>
+#include <grub/i386/io.h>
+
+#define GRUB_CMOS_ADDR_REG 0x70
+#define GRUB_CMOS_DATA_REG 0x71
+
+#define GRUB_CMOS_INDEX_SECOND 0
+#define GRUB_CMOS_INDEX_SECOND_ALARM 1
+#define GRUB_CMOS_INDEX_MINUTE 2
+#define GRUB_CMOS_INDEX_MINUTE_ALARM 3
+#define GRUB_CMOS_INDEX_HOUR 4
+#define GRUB_CMOS_INDEX_HOUR_ALARM 5
+#define GRUB_CMOS_INDEX_DAY_OF_WEEK 6
+#define GRUB_CMOS_INDEX_DAY_OF_MONTH 7
+#define GRUB_CMOS_INDEX_MONTH 8
+#define GRUB_CMOS_INDEX_YEAR 9
+
+#define GRUB_CMOS_INDEX_STATUS_A 0xA
+#define GRUB_CMOS_INDEX_STATUS_B 0xB
+#define GRUB_CMOS_INDEX_STATUS_C 0xC
+#define GRUB_CMOS_INDEX_STATUS_D 0xD
+
+#define GRUB_CMOS_STATUS_B_DAYLIGHT 1
+#define GRUB_CMOS_STATUS_B_24HOUR 2
+#define GRUB_CMOS_STATUS_B_BINARY 4
+
+static inline grub_uint8_t
+grub_bcd_to_num (grub_uint8_t a)
+{
+ return ((a >> 4) * 10 + (a & 0xF));
+}
+
+static inline grub_uint8_t
+grub_num_to_bcd (grub_uint8_t a)
+{
+ return (((a / 10) << 4) + (a % 10));
+}
+
+static inline grub_uint8_t
+grub_cmos_read (grub_uint8_t index)
+{
+ grub_outb (index, GRUB_CMOS_ADDR_REG);
+ return grub_inb (GRUB_CMOS_DATA_REG);
+}
+
+static inline void
+grub_cmos_write (grub_uint8_t index, grub_uint8_t value)
+{
+ grub_outb (index, GRUB_CMOS_ADDR_REG);
+ grub_outb (value, GRUB_CMOS_DATA_REG);
+}
+
+#endif /* GRUB_CPU_CMOS_H */
diff --git a/include/grub/lib/datetime.h b/include/grub/lib/datetime.h
new file mode 100644
index 0000000..7b140cc
--- /dev/null
+++ b/include/grub/lib/datetime.h
@@ -0,0 +1,44 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_DATETIME_HEADER
+#define KERNEL_DATETIME_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+
+struct grub_datetime
+{
+ grub_uint16_t year;
+ grub_uint8_t month;
+ grub_uint8_t day;
+ grub_uint8_t hour;
+ grub_uint8_t minute;
+ grub_uint8_t second;
+};
+
+/* Return date and time. */
+grub_err_t grub_get_datetime (struct grub_datetime *datetime);
+
+/* Set date and time. */
+grub_err_t grub_set_datetime (struct grub_datetime *datetime);
+
+int grub_get_weekday (struct grub_datetime *datetime);
+char *grub_get_weekday_name (struct grub_datetime *datetime);
+
+#endif /* ! KERNEL_DATETIME_HEADER */
diff --git a/kern/env.c b/kern/env.c
index c478648..4a37e9e 100644
--- a/kern/env.c
+++ b/kern/env.c
@@ -146,10 +146,10 @@ grub_env_insert (struct grub_env_context *context,
int idx = grub_env_hashval (var->name);
/* Insert the variable into the hashtable. */
- var->prevp = &context->vars[idx];;
+ var->prevp = &context->vars[idx];
var->next = context->vars[idx];
if (var->next)
- var->next->prevp = &var;
+ var->next->prevp = &(var->next);
context->vars[idx] = var;
}
diff --git a/lib/datetime.c b/lib/datetime.c
new file mode 100644
index 0000000..7215a6a
--- /dev/null
+++ b/lib/datetime.c
@@ -0,0 +1,49 @@
+/* datetime.c - Module for common datetime function. */
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/lib/datetime.h>
+
+static char *grub_weekday_names[] =
+{
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+};
+
+int
+grub_get_weekday (struct grub_datetime *datetime)
+{
+ int a, y, m;
+
+ a = (14 - datetime->month) / 12;
+ y = datetime->year - a;
+ m = datetime->month + 12 * a - 2;
+
+ return (datetime->day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7;
+}
+
+char *
+grub_get_weekday_name (struct grub_datetime *datetime)
+{
+ return grub_weekday_names[grub_get_weekday (datetime)];
+}
diff --git a/lib/efi/datetime.c b/lib/efi/datetime.c
new file mode 100644
index 0000000..9fa72fd
--- /dev/null
+++ b/lib/efi/datetime.c
@@ -0,0 +1,79 @@
+/* kern/efi/datetime.c - efi datetime function.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/lib/datetime.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+ grub_efi_status_t status;
+ struct grub_efi_time efi_time;
+
+ status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
+ &efi_time, 0);
+
+ if (status)
+ return grub_error (GRUB_ERR_INVALID_COMMAND,
+ "can\'t get datetime using efi");
+ else
+ {
+ datetime->year = efi_time.year;
+ datetime->month = efi_time.month;
+ datetime->day = efi_time.day;
+ datetime->hour = efi_time.hour;
+ datetime->minute = efi_time.minute;
+ datetime->second = efi_time.second;
+ }
+
+ return 0;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime)
+{
+ grub_efi_status_t status;
+ struct grub_efi_time efi_time;
+
+ status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
+ &efi_time, 0);
+
+ if (status)
+ return grub_error (GRUB_ERR_INVALID_COMMAND,
+ "can\'t get datetime using efi");
+
+ efi_time.year = datetime->year;
+ efi_time.month = datetime->month;
+ efi_time.day = datetime->day;
+ efi_time.hour = datetime->hour;
+ efi_time.minute = datetime->minute;
+ efi_time.second = datetime->second;
+
+ status = efi_call_1 (grub_efi_system_table->runtime_services->set_time,
+ &efi_time);
+
+ if (status)
+ return grub_error (GRUB_ERR_INVALID_COMMAND,
+ "can\'t set datetime using efi");
+
+ return 0;
+}
diff --git a/lib/i386/datetime.c b/lib/i386/datetime.c
new file mode 100644
index 0000000..1e59746
--- /dev/null
+++ b/lib/i386/datetime.c
@@ -0,0 +1,155 @@
+/* kern/i386/datetime.c - x86 CMOS datetime function.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/lib/datetime.h>
+#include <grub/i386/cmos.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+ int is_bcd, is_12hour;
+ grub_uint8_t value, flag;
+
+ flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+
+ is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_YEAR);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->year = value;
+ datetime->year += (value < 80) ? 2000 : 1900;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->month = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->day = value;
+
+ is_12hour = ! (flag & GRUB_CMOS_STATUS_B_24HOUR);
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_HOUR);
+ if (is_12hour)
+ {
+ is_12hour = (value & 0x80);
+
+ value &= 0x7F;
+ value--;
+ }
+
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ if (is_12hour)
+ value += 12;
+
+ datetime->hour = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->minute = value;
+
+ value = grub_cmos_read (GRUB_CMOS_INDEX_SECOND);
+ if (is_bcd)
+ value = grub_bcd_to_num (value);
+
+ datetime->second = value;
+
+ return 0;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime)
+{
+ int is_bcd, is_12hour;
+ grub_uint8_t value, flag;
+
+ flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+
+ is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
+
+ value = ((datetime->year >= 2000) ? datetime->year - 2000 :
+ datetime->year - 1900);
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value);
+
+ value = datetime->month;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value);
+
+ value = datetime->day;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value);
+
+ value = datetime->hour;
+
+ is_12hour = (! (flag & GRUB_CMOS_STATUS_B_24HOUR));
+
+ if (is_12hour)
+ {
+ value++;
+
+ if (value > 12)
+ value -= 12;
+ else
+ is_12hour = 0;
+ }
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ if (is_12hour)
+ value |= 0x80;
+
+ grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value);
+
+ value = datetime->minute;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value);
+
+ value = datetime->second;
+
+ if (is_bcd)
+ value = grub_num_to_bcd (value);
+
+ grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value);
+
+ return 0;
+}
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-13 1:46 ` Bean
2008-08-13 3:26 ` Bean
@ 2008-08-13 10:17 ` Marco Gerards
2008-08-15 15:38 ` Bean
1 sibling, 1 reply; 28+ messages in thread
From: Marco Gerards @ 2008-08-13 10:17 UTC (permalink / raw)
To: The development of GRUB 2
Hi,
Bean <bean123ch@gmail.com> writes:
>
> Oh, please take a look at my other post "Idea: implementation of the
> password command", it sugguest to implement password with hooks, for
> example, reading $GET_PASSWORD would prompt the user for password and
> return the encrypted form.
>
> BTW, I'm thinking perhaps it's better to move the hook function from
> datetime.mod to datehook.mod, and datetime.mod only contain
> grub_get_datetime, grub_set_datetime, grub_get_weekday and
> grub_get_weekday_name. Module like date.mod only need the datetime
> functions, it's a little wired to install the hook as a side effect.
Fine for me :-)
--
Marco
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] New command checktime
2008-08-13 10:17 ` Marco Gerards
@ 2008-08-15 15:38 ` Bean
0 siblings, 0 replies; 28+ messages in thread
From: Bean @ 2008-08-15 15:38 UTC (permalink / raw)
To: The development of GRUB 2
On Wed, Aug 13, 2008 at 6:17 PM, Marco Gerards <mgerards@xs4all.nl> wrote:
> Hi,
>
> Bean <bean123ch@gmail.com> writes:
>
>>
>> Oh, please take a look at my other post "Idea: implementation of the
>> password command", it sugguest to implement password with hooks, for
>> example, reading $GET_PASSWORD would prompt the user for password and
>> return the encrypted form.
>>
>> BTW, I'm thinking perhaps it's better to move the hook function from
>> datetime.mod to datehook.mod, and datetime.mod only contain
>> grub_get_datetime, grub_set_datetime, grub_get_weekday and
>> grub_get_weekday_name. Module like date.mod only need the datetime
>> functions, it's a little wired to install the hook as a side effect.
>
> Fine for me :-)
Committed.
--
Bean
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2008-08-15 15:38 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-06 11:02 [PATCH] New command checktime Bean
2008-08-06 11:35 ` Robert Millan
2008-08-06 15:09 ` Bean
2008-08-06 19:57 ` Robert Millan
2008-08-07 8:05 ` Bean
2008-08-07 10:21 ` Robert Millan
2008-08-07 11:19 ` Bean
2008-08-07 17:52 ` Bean
2008-08-07 18:17 ` Colin D Bennett
2008-08-07 19:12 ` Robert Millan
2008-08-09 4:34 ` Bean
2008-08-09 11:20 ` Isaac Dupree
2008-08-09 11:37 ` Bean
2008-08-10 9:32 ` Robert Millan
2008-08-10 11:10 ` Bean
2008-08-10 15:15 ` Isaac Dupree
2008-08-10 17:22 ` Robert Millan
2008-08-07 19:06 ` Robert Millan
2008-08-10 18:04 ` Marco Gerards
2008-08-11 11:06 ` Bean
2008-08-11 14:18 ` Robert Millan
2008-08-11 21:07 ` Marco Gerards
2008-08-12 17:13 ` Bean
2008-08-12 21:49 ` Marco Gerards
2008-08-13 1:46 ` Bean
2008-08-13 3:26 ` Bean
2008-08-13 10:17 ` Marco Gerards
2008-08-15 15:38 ` Bean
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.