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 . + */ + +#include +#include +#include +#include +#include +#include + +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