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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +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 . + */ + +#ifndef KERNEL_DATETIME_HEADER +#define KERNEL_DATETIME_HEADER 1 + +#include + +/* 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 . + */ + +#ifndef GRUB_CPU_CMOS_H +#define GRUB_CPU_CMOS_H 1 + +#include +#include + +#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 . + */ + +#include +#include +#include +#include +#include + +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; +}