Hi, 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 The five parameters for checktime is the same as in crontab: minute, hour, day, month and day of week. This command check if the current daytime is within the range specified by the parameters, and return true or false accordingly. Combined this with the script support for grub2, you can perform some operation in a selected time range. The range of the five parameters are: minute: 0-59 hour: 0-23 day of month: 1-31 month 1-12 day of week 0-6 (0 is Sunday) checktime * 12-15 * 1,3-5 * Return true on afternoon of Jan, March, April and May. checktime * * * */2 * Return true on Month 1,3,5,7,9,11 For example, you can use a different background image according to the current season: if checktime * * * 3-5 *; then background_image /spring.png fi if checktime * * * 6-8 *; then background_image /summer.png fi if checktime * * * 9-11 *; then background_image /fall.png fi if checktime * * * 1-2,12 *; then background_image /winter.png fi Or boot a different item in the morning, afternoon and evening. 2008-08-06 Bean <[EMAIL PROTECTED]> * conf/i386-pc.rmk (kernel_img_HEADERS): Add machine/time.h. (pkglib_MODULES): Add chktime.mod. (chktime_mod_SOURCES): New macro. (chktime_mod_CFLAGS): Likewise. (chktime_mod_LDFLAGS): Likewise. * include/grub/i386/pc/time.h: Add function grub_get_datetime. * kern/i386/pc/startup.S: Add function grub_get_datetime. * commands/i386/pc/checktime.c: New file. -- Bean
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 <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/machine/time.h> + +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
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel