On Thu, Aug 7, 2008 at 3:57 AM, Robert Millan <[EMAIL PROTECTED]> wrote:
> On Wed, Aug 06, 2008 at 11:09:44PM +0800, Bean wrote:
>> On Wed, Aug 6, 2008 at 7:35 PM, Robert Millan <[EMAIL PROTECTED]> 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  <[EMAIL PROTECTED]>

        * 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
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;
+}
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to