grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] New command checktime


From: Marco Gerards
Subject: Re: [PATCH] New command checktime
Date: Mon, 11 Aug 2008 23:07:11 +0200
User-agent: Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux)

Bean <address@hidden> writes:

> On Mon, Aug 11, 2008 at 2:04 AM, Marco Gerards <address@hidden> wrote:
>> Hi,
>>
>> Bean <address@hidden> 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  <address@hidden>
>
>       * 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
> address@hidden
> http://lists.gnu.org/mailman/listinfo/grub-devel





reply via email to

[Prev in Thread] Current Thread [Next in Thread]