On Thu, Aug 7, 2008 at 7:19 PM, Bean <[EMAIL PROTECTED]> wrote:
> On Thu, Aug 7, 2008 at 6:21 PM, Robert Millan <[EMAIL PROTECTED]> 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  <[EMAIL PROTECTED]>

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

Reply via email to