=== modified file 'ChangeLog' --- ChangeLog 2008-07-27 19:57:43 +0000 +++ ChangeLog 2008-07-28 16:51:30 +0000 @@ -1,3 +1,68 @@ +2008-07-28 Colin D Bennett + + High resolution timer support. Implemented for x86 CPUs using TSC. + Extracted generic grub_millisleep() so it's linked in only as needed. + This requires a Pentium compatible CPU; if the RDTSC instruction is + not supported, then it falls back on the generic grub_get_time_ms() + implementation that uses the machine's RTC. + + * conf/i386-efi.rmk: Added new source files to kernel_elf_SOURCES. + + * conf/i386-pc.rmk: Likewise. + + * conf/sparc64-ieee1275.rmk: Likewise. + + * conf/powerpc-ieee1275.rmk: Likewise. + + * conf/i386-coreboot.rmk: Likewise. + + * kern/generic/rtc_get_time_ms.c: New file. + + * kern/generic/millisleep.c: New file. + + * kern/misc.c (grub_millisleep_generic): Removed. + + * commands/sleep.c (grub_interruptible_millisleep): Uses + grub_get_time_ms() instead of grub_get_rtc() to stay in sync with + grub_millisleep() from kern/generic/millisleep.c. + + * include/grub/i386/tsc.h (grub_get_tsc): New file. New inline + function. + (grub_cpu_is_cpuid_supported): New inline function. + (grub_cpu_is_tsc_supported): New inline function. + (grub_tsc_init): New function prototype. + (grub_tsc_get_time_ms): New function prototype. + + * kern/i386/tsc.c (grub_get_time_ms): New file. New function. + (calibrate_tsc): New static function. + (grub_tsc_init): New function. + + * include/grub/time.h (grub_millisleep_generic): Removed. + (grub_get_time_ms): New function. + (grub_install_get_time_ms): New function. + + * kern/time.c (grub_get_time_ms): New function. + (grub_install_get_time_ms): New function. + + * kern/i386/efi/init.c (grub_millisleep): Removed. + (grub_machine_init): Call grub_tsc_init. + + * kern/i386/linuxbios/init.c (grub_machine_init): Install the RTC + get_time_ms() implementation. + + * kern/sparc64/ieee1275/init.c (grub_millisleep): Removed. + (ieee1275_get_time_ms): New function. + (grub_machine_init): Install get_time_ms() implementation. + + * kern/i386/pc/init.c (grub_machine_init): Call grub_tsc_init(). + (grub_millisleep): Removed. + + * kern/ieee1275/init.c (grub_millisleep): Removed. + (grub_machine_init): Install ieee1275_get_time_ms() implementation. + (ieee1275_get_time_ms): New static function. + (grub_get_rtc): Now calls ieee1275_get_time_ms(), which does the real + work. + 2008-07-27 Robert Millan * disk/ata.c (grub_ata_dumpinfo): Use grub_dprintf() for debugging === modified file 'commands/sleep.c' --- commands/sleep.c 2008-05-16 20:55:29 +0000 +++ commands/sleep.c 2008-07-04 16:55:48 +0000 @@ -43,15 +43,15 @@ grub_printf ("%d ", n); } -/* Based on grub_millisleep() from kern/misc.c. */ +/* Based on grub_millisleep() from kern/generic/millisleep.c. */ static int grub_interruptible_millisleep (grub_uint32_t ms) { - grub_uint32_t end_at; - - end_at = grub_get_rtc () + grub_div_roundup (ms * GRUB_TICKS_PER_SECOND, 1000); - - while (grub_get_rtc () < end_at) + grub_uint64_t start; + + start = grub_get_time_ms (); + + while (grub_get_time_ms () - start < ms) if (grub_checkkey () >= 0 && GRUB_TERM_ASCII_CHAR (grub_getkey ()) == GRUB_TERM_ESC) return 1; === modified file 'conf/i386-coreboot.rmk' --- conf/i386-coreboot.rmk 2008-07-27 12:51:30 +0000 +++ conf/i386-coreboot.rmk 2008-07-28 16:23:46 +0000 @@ -16,6 +16,7 @@ kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \ + kern/time.c \ kern/i386/dl.c kern/parser.c kern/partition.c \ kern/env.c \ term/i386/pc/console.c \ === modified file 'conf/i386-efi.rmk' --- conf/i386-efi.rmk 2008-07-27 12:51:30 +0000 +++ conf/i386-efi.rmk 2008-07-28 16:23:46 +0000 @@ -84,7 +84,10 @@ kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \ kern/i386/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ - term/efi/console.c disk/efi/efidisk.c + term/efi/console.c disk/efi/efidisk.c \ + kern/i386/tsc.c \ + kern/generic/rtc_get_time_ms.c \ + kern/generic/millisleep.c kernel_mod_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \ partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \ === modified file 'conf/i386-ieee1275.rmk' --- conf/i386-ieee1275.rmk 2008-07-27 12:51:30 +0000 +++ conf/i386-ieee1275.rmk 2008-07-28 16:23:46 +0000 @@ -19,6 +19,7 @@ kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \ kern/i386/dl.c kern/parser.c kern/partition.c \ kern/env.c \ + kern/generic/millisleep.c \ kern/ieee1275/ieee1275.c \ term/ieee1275/ofconsole.c term/i386/pc/at_keyboard.c \ disk/ieee1275/ofdisk.c \ === modified file 'conf/i386-pc.rmk' --- conf/i386-pc.rmk 2008-07-27 12:51:30 +0000 +++ conf/i386-pc.rmk 2008-07-28 16:23:46 +0000 @@ -42,7 +42,11 @@ kernel_img_SOURCES = kern/i386/pc/startup.S kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \ + kern/time.c \ kern/i386/dl.c kern/i386/pc/init.c kern/parser.c kern/partition.c \ + kern/i386/tsc.c \ + kern/generic/rtc_get_time_ms.c \ + kern/generic/millisleep.c \ kern/env.c \ term/i386/pc/console.c \ symlist.c === modified file 'conf/powerpc-ieee1275.rmk' --- conf/powerpc-ieee1275.rmk 2008-07-27 12:51:30 +0000 +++ conf/powerpc-ieee1275.rmk 2008-07-28 13:59:50 +0000 @@ -85,6 +85,7 @@ kern/ieee1275/init.c term/ieee1275/ofconsole.c \ kern/ieee1275/openfw.c disk/ieee1275/ofdisk.c \ kern/parser.c kern/partition.c kern/env.c kern/powerpc/dl.c \ + kern/generic/millisleep.c \ symlist.c kern/powerpc/cache.S kernel_elf_HEADERS = grub/powerpc/ieee1275/ieee1275.h kernel_elf_CFLAGS = $(COMMON_CFLAGS) === modified file 'conf/sparc64-ieee1275.rmk' --- conf/sparc64-ieee1275.rmk 2008-06-19 00:04:59 +0000 +++ conf/sparc64-ieee1275.rmk 2008-07-03 04:19:16 +0000 @@ -73,6 +73,7 @@ kern/rescue.c kern/term.c term/ieee1275/ofconsole.c \ kern/sparc64/ieee1275/openfw.c disk/ieee1275/ofdisk.c \ kern/partition.c kern/env.c kern/sparc64/dl.c symlist.c \ + kern/generic/millisleep.c kern/generic/get_time_ms.c \ kern/sparc64/cache.S kern/parser.c kernel_elf_HEADERS = grub/sparc64/ieee1275/ieee1275.h kernel_elf_CFLAGS = $(COMMON_CFLAGS) === modified file 'conf/x86_64-efi.rmk' --- conf/x86_64-efi.rmk 2008-07-27 12:51:30 +0000 +++ conf/x86_64-efi.rmk 2008-07-28 16:23:46 +0000 @@ -87,6 +87,7 @@ kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \ kern/x86_64/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ + kern/generic/millisleep.c kern/generic/rtc_get_time_ms.c \ term/efi/console.c disk/efi/efidisk.c kernel_mod_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \ === added file 'include/grub/i386/tsc.h' --- include/grub/i386/tsc.h 1970-01-01 00:00:00 +0000 +++ include/grub/i386/tsc.h 2008-07-28 16:23:46 +0000 @@ -0,0 +1,80 @@ +/* + * 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_CPU_TSC_HEADER +#define KERNEL_CPU_TSC_HEADER 1 + +#include + +/* Read the TSC value, which increments with each CPU clock cycle. */ +static __inline grub_uint64_t +grub_get_tsc (void) +{ + grub_uint32_t lo, hi; + + /* The CPUID instruction is a 'serializing' instruction, and + avoids out-of-order execution of the RDTSC instruction. */ + __asm__ __volatile__ ("xorl %%eax, %%eax\n\t" + "cpuid":::"%rax", "%rbx", "%rcx", "%rdx"); + /* Read TSC value. We cannot use "=A", since this would use + %rax on x86_64. */ + __asm__ __volatile__ ("rdtsc":"=a" (lo), "=d" (hi)); + + return (((grub_uint64_t) hi) << 32) | lo; +} + +static __inline int +grub_cpu_is_cpuid_supported (void) +{ + grub_uint32_t id_supported; + + __asm__ ("pushfl\n\t" + "popl %%eax /* Get EFLAGS into EAX */\n\t" + "movl %%eax, %%ecx /* Save original flags in ECX */\n\t" + "xorl $0x200000, %%eax /* Flip ID bit in EFLAGS */\n\t" + "pushl %%eax /* Store modified EFLAGS on stack */\n\t" + "popfl /* Replace current EFLAGS */\n\t" + "pushfl /* Read back the EFLAGS */\n\t" + "popl %%eax /* Get EFLAGS into EAX */\n\t" + "xorl %%ecx, %%eax /* Check if flag could be modified */\n\t" + : "=a" (id_supported) + : /* No inputs. */ + : /* Clobbered: */ "%rcx"); + + return id_supported != 0; +} + +static __inline int +grub_cpu_is_tsc_supported (void) +{ + if (! grub_cpu_is_cpuid_supported ()) + return 0; + + grub_uint32_t features; + __asm__ ("movl $1, %%eax\n\t" + "cpuid" + : "=d" (features) + : /* No inputs. */ + : /* Clobbered: */ "%rax", "%rbx", "%rcx"); + return (features & (1 << 4)) != 0; +} + +void grub_tsc_init (void); +grub_uint64_t grub_tsc_get_time_ms (void); + +#endif /* ! KERNEL_CPU_TSC_HEADER */ === modified file 'include/grub/time.h' --- include/grub/time.h 2007-10-22 19:02:16 +0000 +++ include/grub/time.h 2008-07-28 16:51:30 +0000 @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2007 Free Software Foundation, Inc. + * Copyright (C) 2007, 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 @@ -19,12 +19,15 @@ #ifndef KERNEL_TIME_HEADER #define KERNEL_TIME_HEADER 1 +#include #include #include #include void EXPORT_FUNC(grub_millisleep) (grub_uint32_t ms); -void EXPORT_FUNC(grub_millisleep_generic) (grub_uint32_t ms); +grub_uint64_t EXPORT_FUNC(grub_get_time_ms) (void); + +grub_uint64_t grub_rtc_get_time_ms (void); static __inline void grub_sleep (grub_uint32_t s) @@ -32,4 +35,6 @@ grub_millisleep (1000 * s); } +void grub_install_get_time_ms (grub_uint64_t (*get_time_ms_func) (void)); + #endif /* ! KERNEL_TIME_HEADER */ === added directory 'kern/generic' === added file 'kern/generic/millisleep.c' --- kern/generic/millisleep.c 1970-01-01 00:00:00 +0000 +++ kern/generic/millisleep.c 2008-07-28 16:51:30 +0000 @@ -0,0 +1,39 @@ +/* millisleep.c - generic millisleep function. + * The generic implementation of these functions can be used for architectures + * or platforms that do not have a more specialized implementation. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,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 + +void +grub_millisleep (grub_uint32_t ms) +{ + grub_uint64_t start; + + start = grub_get_time_ms (); + + /* Instead of setting an end time and looping while the current time is + less than that, comparing the elapsed sleep time with the desired sleep + time handles the (unlikely!) case that the timer would wrap around + during the sleep. */ + + while (grub_get_time_ms () - start < ms) + grub_cpu_idle (); +} === added file 'kern/generic/rtc_get_time_ms.c' --- kern/generic/rtc_get_time_ms.c 1970-01-01 00:00:00 +0000 +++ kern/generic/rtc_get_time_ms.c 2008-07-28 16:51:30 +0000 @@ -0,0 +1,37 @@ +/* rtc_get_time_ms.c - get_time_ms implementation using platform RTC. + * The generic implementation of these functions can be used for architectures + * or platforms that do not have a more specialized implementation. */ +/* + * 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 + +/* Calculate the time in milliseconds since the epoch based on the RTC. */ +grub_uint64_t +grub_rtc_get_time_ms (void) +{ + /* By dimensional analysis: + + 1000 ms N rtc ticks 1 s + ------- * ----------- * ----------- = 1000*N/T ms + 1 s 1 T rtc ticks + */ + grub_uint64_t ticks_ms_per_sec = ((grub_uint64_t) 1000) * grub_get_rtc (); + return grub_divmod64 (ticks_ms_per_sec, GRUB_TICKS_PER_SECOND, 0); +} === modified file 'kern/i386/efi/init.c' --- kern/i386/efi/init.c 2007-10-22 18:59:33 +0000 +++ kern/i386/efi/init.c 2008-07-28 16:23:46 +0000 @@ -25,18 +25,13 @@ #include #include #include -#include - -void -grub_millisleep (grub_uint32_t ms) -{ - grub_millisleep_generic (ms); -} +#include void grub_machine_init (void) { grub_efi_init (); + grub_tsc_init (); } void === modified file 'kern/i386/linuxbios/init.c' --- kern/i386/linuxbios/init.c 2008-07-04 02:26:10 +0000 +++ kern/i386/linuxbios/init.c 2008-07-28 16:23:46 +0000 @@ -149,6 +149,8 @@ /* This variable indicates size, not offset. */ grub_upper_mem -= GRUB_MEMORY_MACHINE_UPPER_START; + + grub_install_get_time_ms (grub_rtc_get_time_ms); } void === modified file 'kern/i386/pc/init.c' --- kern/i386/pc/init.c 2008-06-15 17:21:16 +0000 +++ kern/i386/pc/init.c 2008-07-28 16:23:46 +0000 @@ -30,6 +30,7 @@ #include #include #include +#include struct mem_region { @@ -46,12 +47,6 @@ grub_size_t grub_os_area_size; grub_size_t grub_lower_mem, grub_upper_mem; -void -grub_millisleep (grub_uint32_t ms) -{ - grub_millisleep_generic (ms); -} - void grub_arch_sync_caches (void *address __attribute__ ((unused)), grub_size_t len __attribute__ ((unused))) @@ -231,6 +226,8 @@ if (! grub_os_area_addr) grub_fatal ("no upper memory"); + + grub_tsc_init (); } void === added file 'kern/i386/tsc.c' --- kern/i386/tsc.c 1970-01-01 00:00:00 +0000 +++ kern/i386/tsc.c 2008-07-28 16:51:30 +0000 @@ -0,0 +1,102 @@ +/* kern/i386/tsc.c - x86 TSC time source implementation + * Requires Pentium or better x86 CPU that supports the RDTSC instruction. + * This module uses the RTC (via grub_get_rtc()) to calibrate the TSC to + * real 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 + +/* Calibrated reference for TSC=0. This defines the time since the epoch in + milliseconds that TSC=0 refers to. */ +static grub_uint64_t tsc_boot_time; + +/* Calibrated TSC rate. (In TSC ticks per millisecond.) */ +static grub_uint64_t tsc_ticks_per_ms; + + +grub_uint64_t +grub_tsc_get_time_ms (void) +{ + return tsc_boot_time + grub_divmod64 (grub_get_tsc (), tsc_ticks_per_ms, 0); +} + + +/* How many RTC ticks to use for calibration loop. (>= 1) */ +#define CALIBRATION_TICKS 2 + +/* Calibrate the TSC based on the RTC. */ +static void +calibrate_tsc (void) +{ + /* First calbrate the TSC rate (relative, not absolute time). */ + grub_uint64_t start_tsc; + grub_uint64_t end_tsc; + grub_uint32_t initial_tick; + grub_uint32_t start_tick; + grub_uint32_t end_tick; + + /* Wait for the start of the next tick; + we'll base out timing off this edge. */ + initial_tick = grub_get_rtc (); + do + { + start_tick = grub_get_rtc (); + } + while (start_tick == initial_tick); + start_tsc = grub_get_tsc (); + + /* Wait for the start of the next tick. This will + be the end of the 1-tick period. */ + do + { + end_tick = grub_get_rtc (); + } + while (end_tick - start_tick < CALIBRATION_TICKS); + end_tsc = grub_get_tsc (); + + tsc_ticks_per_ms = + grub_divmod64 (grub_divmod64 + (end_tsc - start_tsc, end_tick - start_tick, 0) + * GRUB_TICKS_PER_SECOND, 1000, 0); + + /* Reference the TSC zero (boot time) to the epoch to + get an absolute real time reference. */ + grub_uint64_t ms_since_boot = grub_divmod64 (end_tsc, tsc_ticks_per_ms, 0); + grub_uint64_t mstime_now = grub_divmod64 ((grub_uint64_t) 1000 * end_tick, + GRUB_TICKS_PER_SECOND, + 0); + tsc_boot_time = mstime_now - ms_since_boot; +} + +void +grub_tsc_init (void) +{ + if (grub_cpu_is_tsc_supported ()) + { + calibrate_tsc (); + grub_install_get_time_ms (grub_tsc_get_time_ms); + } + else + { + grub_install_get_time_ms (grub_rtc_get_time_ms); + } +} === modified file 'kern/ieee1275/init.c' --- kern/ieee1275/init.c 2008-07-04 02:01:55 +0000 +++ kern/ieee1275/init.c 2008-07-28 16:23:46 +0000 @@ -47,12 +47,6 @@ extern char _end[]; void -grub_millisleep (grub_uint32_t ms) -{ - grub_millisleep_generic (ms); -} - -void grub_exit (void) { grub_ieee1275_exit (); @@ -202,6 +196,8 @@ #endif +static grub_uint64_t ieee1275_get_time_ms (void); + void grub_machine_init (void) { @@ -251,6 +247,8 @@ } } } + + grub_install_get_time_ms (ieee1275_get_time_ms); } void @@ -260,8 +258,8 @@ grub_console_fini (); } -grub_uint32_t -grub_get_rtc (void) +static grub_uint64_t +ieee1275_get_time_ms (void) { grub_uint32_t msecs = 0; @@ -270,6 +268,12 @@ return msecs; } +grub_uint32_t +grub_get_rtc (void) +{ + return ieee1275_get_time_ms (); +} + grub_addr_t grub_arch_modules_addr (void) { === modified file 'kern/misc.c' --- kern/misc.c 2008-06-15 23:42:48 +0000 +++ kern/misc.c 2008-07-04 18:03:26 +0000 @@ -23,7 +23,6 @@ #include #include #include -#include void * grub_memmove (void *dest, const void *src, grub_size_t n) @@ -1018,17 +1017,6 @@ return p - dest; } -void -grub_millisleep_generic (grub_uint32_t ms) -{ - grub_uint32_t end_at; - - end_at = grub_get_rtc () + grub_div_roundup (ms * GRUB_TICKS_PER_SECOND, 1000); - - while (grub_get_rtc () < end_at) - grub_cpu_idle (); -} - /* Abort GRUB. This function does not return. */ void grub_abort (void) === modified file 'kern/sparc64/ieee1275/init.c' --- kern/sparc64/ieee1275/init.c 2007-10-22 18:59:33 +0000 +++ kern/sparc64/ieee1275/init.c 2008-07-28 16:23:46 +0000 @@ -66,12 +66,6 @@ /* Never reached. */ } -void -grub_millisleep (grub_uint32_t ms) -{ - grub_millisleep_generic (ms); -} - int grub_ieee1275_test_flag (enum grub_ieee1275_flag flag) { @@ -145,6 +139,8 @@ grub_free (prefix); } +grub_uint64_t ieee1275_get_time_ms (void); + void grub_machine_init (void) { @@ -201,6 +197,7 @@ } } + grub_install_get_time_ms (ieee1275_get_time_ms); } void @@ -216,6 +213,12 @@ grub_ieee1275_enter (); } +grub_uint64_t +ieee1275_get_time_ms (void) +{ + return grub_get_rtc (); +} + grub_uint32_t grub_get_rtc (void) { === added file 'kern/time.c' --- kern/time.c 1970-01-01 00:00:00 +0000 +++ kern/time.c 2008-07-28 16:23:46 +0000 @@ -0,0 +1,37 @@ +/* time.c - kernel time functions */ +/* + * 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 + +typedef grub_uint64_t (*get_time_ms_func_t) (void); + +/* Function pointer to the implementation in use. */ +static get_time_ms_func_t get_time_ms_func; + +grub_uint64_t +grub_get_time_ms (void) +{ + return get_time_ms_func (); +} + +void +grub_install_get_time_ms (get_time_ms_func_t func) +{ + get_time_ms_func = func; +}