Merge mainline into newreloc. For now without boot tests

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-08-25 03:25:18 +02:00
commit 16bd6cfab2
625 changed files with 45066 additions and 10823 deletions

View file

@ -0,0 +1,139 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009 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/kernel.h>
#include <grub/mm.h>
#include <grub/machine/time.h>
#include <grub/machine/init.h>
#include <grub/machine/memory.h>
#include <grub/machine/console.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/loader.h>
#include <grub/env.h>
#include <grub/cache.h>
#include <grub/time.h>
#include <grub/symbol.h>
#include <grub/cpu/io.h>
#include <grub/cpu/tsc.h>
#ifdef GRUB_MACHINE_QEMU
#include <grub/machine/kernel.h>
#endif
#define GRUB_FLOPPY_REG_DIGITAL_OUTPUT 0x3f2
extern char _start[];
extern char _end[];
grub_uint32_t
grub_get_rtc (void)
{
grub_fatal ("grub_get_rtc() is not implemented.\n");
}
/* Stop the floppy drive from spinning, so that other software is
jumped to with a known state. */
void
grub_stop_floppy (void)
{
grub_outb (0, GRUB_FLOPPY_REG_DIGITAL_OUTPUT);
}
void
grub_exit (void)
{
/* We can't use grub_fatal() in this function. This would create an infinite
loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit(). */
while (1)
grub_cpu_idle ();
}
void
grub_machine_init (void)
{
#ifdef GRUB_MACHINE_QEMU
grub_qemu_init_cirrus ();
#endif
/* Initialize the console as early as possible. */
grub_vga_text_init ();
auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
{
#if GRUB_CPU_SIZEOF_VOID_P == 4
/* Restrict ourselves to 32-bit memory space. */
if (addr > GRUB_ULONG_MAX)
return 0;
if (addr + size > GRUB_ULONG_MAX)
size = GRUB_ULONG_MAX - addr;
#endif
if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
return 0;
/* Avoid the lower memory. */
if (addr < GRUB_MEMORY_MACHINE_LOWER_SIZE)
{
if (addr + size <= GRUB_MEMORY_MACHINE_LOWER_SIZE)
return 0;
else
{
size -= GRUB_MEMORY_MACHINE_LOWER_SIZE - addr;
addr = GRUB_MEMORY_MACHINE_LOWER_SIZE;
}
}
grub_mm_init_region ((void *) (grub_addr_t) addr, (grub_size_t) size);
return 0;
}
#if defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU)
grub_machine_mmap_init ();
#endif
grub_machine_mmap_iterate (heap_init);
grub_tsc_init ();
}
void
grub_machine_set_prefix (void)
{
/* Initialize the prefix. */
grub_env_set ("prefix", grub_prefix);
}
void
grub_machine_fini (void)
{
grub_vga_text_fini ();
grub_stop_floppy ();
}
/* Return the end of the core image. */
grub_addr_t
grub_arch_modules_addr (void)
{
#ifdef GRUB_MACHINE_QEMU
return grub_core_entry_addr + grub_kernel_image_size;
#else
return ALIGN_UP((grub_addr_t) _end, GRUB_KERNEL_MACHINE_MOD_ALIGN);
#endif
}

View file

@ -0,0 +1,107 @@
/*
* GRUB -- GRand Unified Bootloader
* 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
* 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/machine/memory.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/misc.h>
static grub_err_t
grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t))
{
grub_linuxbios_table_header_t table_header;
grub_linuxbios_table_item_t table_item;
auto int check_signature (grub_linuxbios_table_header_t);
int check_signature (grub_linuxbios_table_header_t tbl_header)
{
if (! grub_memcmp (tbl_header->signature, "LBIO", 4))
return 1;
return 0;
}
/* Assuming table_header is aligned to its size (8 bytes). */
for (table_header = (grub_linuxbios_table_header_t) 0x500;
table_header < (grub_linuxbios_table_header_t) 0x1000; table_header++)
if (check_signature (table_header))
goto signature_found;
for (table_header = (grub_linuxbios_table_header_t) 0xf0000;
table_header < (grub_linuxbios_table_header_t) 0x100000; table_header++)
if (check_signature (table_header))
goto signature_found;
grub_fatal ("Could not find coreboot table\n");
signature_found:
table_item =
(grub_linuxbios_table_item_t) ((long) table_header +
(long) table_header->size);
for (; table_item->size;
table_item = (grub_linuxbios_table_item_t) ((long) table_item + (long) table_item->size))
{
if (table_item->tag == GRUB_LINUXBIOS_MEMBER_LINK
&& check_signature ((grub_linuxbios_table_header_t) (grub_addr_t)
*(grub_uint64_t *) (table_item + 1)))
{
table_header = (grub_linuxbios_table_header_t) (grub_addr_t)
*(grub_uint64_t *) (table_item + 1);
goto signature_found;
}
if (hook (table_item))
return 1;
}
return 0;
}
grub_err_t
grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
{
mem_region_t mem_region;
auto int iterate_linuxbios_table (grub_linuxbios_table_item_t);
int iterate_linuxbios_table (grub_linuxbios_table_item_t table_item)
{
if (table_item->tag != GRUB_LINUXBIOS_MEMBER_MEMORY)
return 0;
mem_region =
(mem_region_t) ((long) table_item +
sizeof (struct grub_linuxbios_table_item));
while ((long) mem_region < (long) table_item + (long) table_item->size)
{
if (hook (mem_region->addr, mem_region->size,
/* Multiboot mmaps match with the coreboot mmap definition.
Therefore, we can just pass type through. */
mem_region->type))
return 1;
mem_region++;
}
return 0;
}
grub_linuxbios_table_iterate (iterate_linuxbios_table);
return 0;
}

View file

@ -0,0 +1,87 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,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 <http://www.gnu.org/licenses/>.
*/
#include <grub/symbol.h>
#include <grub/machine/memory.h>
#include <grub/cpu/linux.h>
#include <grub/offsets.h>
#include <multiboot.h>
#include <multiboot2.h>
/*
* Note: GRUB is compiled with the options -mrtd and -mregparm=3.
* So the first three arguments are passed in %eax, %edx, and %ecx,
* respectively, and if a function has a fixed number of arguments
* and the number if greater than three, the function must return
* with "ret $N" where N is ((the number of arguments) - 3) * 4.
*/
.file "startup.S"
.text
.globl start, _start
start:
_start:
jmp codestart
/*
* This is a special data area at a fixed offset from the beginning.
*/
. = _start + GRUB_KERNEL_MACHINE_PREFIX
VARIABLE(grub_prefix)
/* to be filled by grub-mkimage */
/*
* Leave some breathing room for the prefix.
*/
. = _start + GRUB_KERNEL_MACHINE_DATA_END
/*
* Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
*/
.p2align 2 /* force 4-byte alignment */
multiboot_header:
/* magic */
.long 0x1BADB002
/* flags */
.long MULTIBOOT_MEMORY_INFO
/* checksum */
.long -0x1BADB002 - MULTIBOOT_MEMORY_INFO
codestart:
#ifdef GRUB_MACHINE_MULTIBOOT
cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
jne 0f
movl %ebx, EXT_C(startup_multiboot_info)
0:
#endif
/* initialize the stack */
movl $GRUB_MEMORY_MACHINE_PROT_STACK, %esp
/* jump to the main body of C code */
jmp EXT_C(grub_main)
/*
* prot_to_real and associated structures (but NOT real_to_prot, that is
* only needed for BIOS gates).
*/
#include "../realmode.S"

109
grub-core/kern/i386/dl.c Normal file
View file

@ -0,0 +1,109 @@
/* dl-386.c - arch-dependent part of loadable module support */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2005,2007,2009 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/dl.h>
#include <grub/elf.h>
#include <grub/misc.h>
#include <grub/err.h>
/* Check if EHDR is a valid ELF header. */
grub_err_t
grub_arch_dl_check_header (void *ehdr)
{
Elf_Ehdr *e = ehdr;
/* Check the magic numbers. */
if (e->e_ident[EI_CLASS] != ELFCLASS32
|| e->e_ident[EI_DATA] != ELFDATA2LSB
|| e->e_machine != EM_386)
return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic");
return GRUB_ERR_NONE;
}
/* Relocate symbols. */
grub_err_t
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
{
Elf_Ehdr *e = ehdr;
Elf_Shdr *s;
Elf_Word entsize;
unsigned i;
/* Find a symbol table. */
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
i < e->e_shnum;
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
if (s->sh_type == SHT_SYMTAB)
break;
if (i == e->e_shnum)
return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
entsize = s->sh_entsize;
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
i < e->e_shnum;
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
if (s->sh_type == SHT_REL)
{
grub_dl_segment_t seg;
/* Find the target segment. */
for (seg = mod->segment; seg; seg = seg->next)
if (seg->section == s->sh_info)
break;
if (seg)
{
Elf_Rel *rel, *max;
for (rel = (Elf_Rel *) ((char *) e + s->sh_offset),
max = rel + s->sh_size / s->sh_entsize;
rel < max;
rel++)
{
Elf_Word *addr;
Elf_Sym *sym;
if (seg->size < rel->r_offset)
return grub_error (GRUB_ERR_BAD_MODULE,
"reloc offset is out of the segment");
addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset);
sym = (Elf_Sym *) ((char *) mod->symtab
+ entsize * ELF_R_SYM (rel->r_info));
switch (ELF_R_TYPE (rel->r_info))
{
case R_386_32:
*addr += sym->st_value;
break;
case R_386_PC32:
*addr += (sym->st_value - (Elf_Word) seg->addr
- rel->r_offset);
break;
}
}
}
}
return GRUB_ERR_NONE;
}

View file

@ -0,0 +1,47 @@
/* init.c - initialize an x86-based EFI system */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007 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/misc.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/cache.h>
#include <grub/kernel.h>
#include <grub/efi/efi.h>
#include <grub/i386/tsc.h>
void
grub_machine_init (void)
{
grub_efi_init ();
grub_tsc_init ();
}
void
grub_machine_fini (void)
{
grub_efi_fini ();
}
void
grub_machine_set_prefix (void)
{
grub_efi_set_prefix ();
}

View file

@ -0,0 +1,66 @@
/* startup.S - bootstrap GRUB itself */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2010 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 <config.h>
#include <grub/symbol.h>
#include <grub/boot.h>
.file "startup.S"
.text
.globl start, _start
start:
_start:
jmp codestart
/*
* Compatibility version number
*
* These MUST be at byte offset 6 and 7 of the executable
* DO NOT MOVE !!!
*/
. = _start + 0x6
.byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
/*
* This is a special data area 8 bytes from the beginning.
*/
. = _start + 0x8
VARIABLE(grub_prefix)
/* to be filled by grub-mkimage */
/*
* Leave some breathing room for the prefix.
*/
. = _start + 0x50
codestart:
/*
* EFI_SYSTEM_TABLE * and EFI_HANDLE are passed on the stack.
*/
movl 4(%esp), %eax
movl %eax, EXT_C(grub_efi_image_handle)
movl 8(%esp), %eax
movl %eax, EXT_C(grub_efi_system_table)
call EXT_C(grub_main)
ret
#include "../realmode.S"

View file

@ -0,0 +1,42 @@
/*
* 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/cpu/io.h>
#include <grub/machine/init.h>
#include <grub/misc.h>
const char bochs_shutdown[] = "Shutdown";
void
grub_halt (void)
{
unsigned int i;
/* Disable interrupts. */
__asm__ __volatile__ ("cli");
/* Bochs, QEMU, etc. */
for (i = 0; i < sizeof (bochs_shutdown) - 1; i++)
grub_outb (bochs_shutdown[i], 0x8900);
grub_printf ("GRUB doesn't know how to halt this machine yet!\n");
/* In order to return we'd have to check what the previous status of IF
flag was. But user most likely doesn't want to return anyway ... */
grub_stop ();
}

View file

@ -0,0 +1,28 @@
/* init.c -- Initialize GRUB on Open Firmware. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,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 <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/cache.h>
void grub_stop_floppy (void);
void
grub_stop_floppy (void)
{
}

View file

@ -0,0 +1,65 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,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 <http://www.gnu.org/licenses/>.
*/
#include <grub/symbol.h>
#include <grub/machine/memory.h>
#include <grub/cpu/linux.h>
#include <multiboot.h>
#include <multiboot2.h>
/*
* Note: GRUB is compiled with the options -mrtd and -mregparm=3.
* So the first three arguments are passed in %eax, %edx, and %ecx,
* respectively, and if a function has a fixed number of arguments
* and the number if greater than three, the function must return
* with "ret $N" where N is ((the number of arguments) - 3) * 4.
*/
.file "startup.S"
.text
.globl start, _start
start:
_start:
jmp codestart
/*
* This is a special data area at a fixed offset from the beginning.
*/
. = _start + GRUB_KERNEL_MACHINE_PREFIX
VARIABLE(grub_prefix)
/* to be filled by grub-mkimage */
/*
* Leave some breathing room for the prefix.
*/
. = _start + GRUB_KERNEL_MACHINE_DATA_END
codestart:
movl %eax, EXT_C(grub_ieee1275_entry_fn)
jmp EXT_C(grub_main)
/*
* prot_to_real and associated structures (but NOT real_to_prot, that is
* only needed for BIOS gates).
*/
#include "../realmode.S"

View file

@ -0,0 +1,29 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,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 <http://www.gnu.org/licenses/>.
*/
#include <grub/symbol.h>
.text
/*
* This call is special... it never returns... in fact it should simply
* hang at this point!
*/
FUNCTION(grub_stop)
cli
1: hlt
jmp 1b

View file

@ -0,0 +1,87 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009 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/machine/init.h>
#include <grub/machine/memory.h>
#include <grub/types.h>
#include <grub/multiboot.h>
#include <grub/err.h>
#include <grub/misc.h>
grub_size_t grub_lower_mem, grub_upper_mem;
/* A pointer to the MBI in its initial location. */
struct multiboot_info *startup_multiboot_info;
/* The MBI has to be copied to our BSS so that it won't be
overwritten. This is its final location. */
static struct multiboot_info kern_multiboot_info;
/* Unfortunately we can't use heap at this point. But 32 looks like a sane
limit (used by memtest86). */
static grub_uint8_t mmap_entries[sizeof (struct multiboot_mmap_entry) * 32];
void
grub_machine_mmap_init ()
{
if (! startup_multiboot_info)
grub_fatal ("Unable to find Multiboot Information (is CONFIG_MULTIBOOT disabled in coreboot?)");
/* Move MBI to a safe place. */
grub_memmove (&kern_multiboot_info, startup_multiboot_info, sizeof (struct multiboot_info));
if ((kern_multiboot_info.flags & MULTIBOOT_INFO_MEM_MAP) == 0)
grub_fatal ("Missing Multiboot memory information");
/* Move the memory map to a safe place. */
if (kern_multiboot_info.mmap_length > sizeof (mmap_entries))
{
grub_printf ("WARNING: Memory map size exceeds limit (0x%x > 0x%x); it will be truncated\n",
kern_multiboot_info.mmap_length, sizeof (mmap_entries));
kern_multiboot_info.mmap_length = sizeof (mmap_entries);
}
grub_memmove (mmap_entries, (void *) kern_multiboot_info.mmap_addr, kern_multiboot_info.mmap_length);
kern_multiboot_info.mmap_addr = (grub_uint32_t) mmap_entries;
if ((kern_multiboot_info.flags & MULTIBOOT_INFO_MEMORY) == 0)
{
grub_lower_mem = GRUB_MEMORY_MACHINE_LOWER_USABLE;
grub_upper_mem = 0;
}
else
{
grub_lower_mem = kern_multiboot_info.mem_lower * 1024;
grub_upper_mem = kern_multiboot_info.mem_upper * 1024;
}
}
grub_err_t
grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
{
struct multiboot_mmap_entry *entry = (void *) kern_multiboot_info.mmap_addr;
while ((unsigned long) entry < kern_multiboot_info.mmap_addr + kern_multiboot_info.mmap_length)
{
if (hook (entry->addr, entry->len, entry->type))
break;
entry = (void *) ((grub_addr_t) entry + entry->size + sizeof (entry->size));
}
return 0;
}

View file

@ -0,0 +1,229 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 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/kernel.h>
#include <grub/mm.h>
#include <grub/machine/boot.h>
#include <grub/machine/init.h>
#include <grub/machine/memory.h>
#include <grub/machine/console.h>
#include <grub/machine/kernel.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/loader.h>
#include <grub/env.h>
#include <grub/cache.h>
#include <grub/time.h>
#include <grub/cpu/tsc.h>
struct mem_region
{
grub_addr_t addr;
grub_size_t size;
};
#define MAX_REGIONS 32
static struct mem_region mem_regions[MAX_REGIONS];
static int num_regions;
static char *
make_install_device (void)
{
/* XXX: This should be enough. */
char dev[100], *ptr = dev;
if (grub_prefix[0] != '(')
{
/* No hardcoded root partition - make it from the boot drive and the
partition number encoded at the install time. */
if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL)
{
grub_strcpy (dev, "(pxe");
ptr += sizeof ("(pxe") - 1;
}
else
{
grub_snprintf (dev, sizeof (dev),
"(%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f',
grub_boot_drive & 0x7f);
ptr += grub_strlen (ptr);
if (grub_install_dos_part >= 0)
grub_snprintf (ptr, sizeof (dev) - (ptr - dev),
",%u", grub_install_dos_part + 1);
ptr += grub_strlen (ptr);
if (grub_install_bsd_part >= 0)
grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ",%u",
grub_install_bsd_part + 1);
ptr += grub_strlen (ptr);
}
grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ")%s", grub_prefix);
grub_strcpy (grub_prefix, dev);
}
else if (grub_prefix[1] == ',' || grub_prefix[1] == ')')
{
/* We have a prefix, but still need to fill in the boot drive. */
grub_snprintf (dev, sizeof (dev),
"(%cd%u%s", (grub_boot_drive & 0x80) ? 'h' : 'f',
grub_boot_drive & 0x7f, grub_prefix + 1);
grub_strcpy (grub_prefix, dev);
}
return grub_prefix;
}
/* Add a memory region. */
static void
add_mem_region (grub_addr_t addr, grub_size_t size)
{
if (num_regions == MAX_REGIONS)
/* Ignore. */
return;
mem_regions[num_regions].addr = addr;
mem_regions[num_regions].size = size;
num_regions++;
}
/* Compact memory regions. */
static void
compact_mem_regions (void)
{
int i, j;
/* Sort them. */
for (i = 0; i < num_regions - 1; i++)
for (j = i + 1; j < num_regions; j++)
if (mem_regions[i].addr > mem_regions[j].addr)
{
struct mem_region tmp = mem_regions[i];
mem_regions[i] = mem_regions[j];
mem_regions[j] = tmp;
}
/* Merge overlaps. */
for (i = 0; i < num_regions - 1; i++)
if (mem_regions[i].addr + mem_regions[i].size >= mem_regions[i + 1].addr)
{
j = i + 1;
if (mem_regions[i].addr + mem_regions[i].size
< mem_regions[j].addr + mem_regions[j].size)
mem_regions[i].size = (mem_regions[j].addr + mem_regions[j].size
- mem_regions[i].addr);
grub_memmove (mem_regions + j, mem_regions + j + 1,
(num_regions - j - 1) * sizeof (struct mem_region));
i--;
num_regions--;
}
}
void
grub_machine_init (void)
{
int i;
int grub_lower_mem;
/* Initialize the console as early as possible. */
grub_console_init ();
grub_lower_mem = grub_get_memsize (0) << 10;
/* Sanity check. */
if (grub_lower_mem < GRUB_MEMORY_MACHINE_RESERVED_END)
grub_fatal ("too small memory");
#if 0
/* Turn on Gate A20 to access >1MB. */
grub_gate_a20 (1);
#endif
/* FIXME: This prevents loader/i386/linux.c from using low memory. When our
heap implements support for requesting a chunk in low memory, this should
no longer be a problem. */
#if 0
/* Add the lower memory into free memory. */
if (grub_lower_mem >= GRUB_MEMORY_MACHINE_RESERVED_END)
add_mem_region (GRUB_MEMORY_MACHINE_RESERVED_END,
grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END);
#endif
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
{
/* Avoid the lower memory. */
if (addr < 0x100000)
{
if (size <= 0x100000 - addr)
return 0;
size -= 0x100000 - addr;
addr = 0x100000;
}
/* Ignore >4GB. */
if (addr <= 0xFFFFFFFF && type == GRUB_MACHINE_MEMORY_AVAILABLE)
{
grub_size_t len;
len = (grub_size_t) ((addr + size > 0xFFFFFFFF)
? 0xFFFFFFFF - addr
: size);
add_mem_region (addr, len);
}
return 0;
}
grub_machine_mmap_iterate (hook);
compact_mem_regions ();
for (i = 0; i < num_regions; i++)
grub_mm_init_region ((void *) mem_regions[i].addr, mem_regions[i].size);
grub_tsc_init ();
}
void
grub_machine_set_prefix (void)
{
/* Initialize the prefix. */
grub_env_set ("prefix", make_install_device ());
}
void
grub_machine_fini (void)
{
grub_console_fini ();
grub_stop_floppy ();
}
/* Return the end of the core image. */
grub_addr_t
grub_arch_modules_addr (void)
{
return GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
+ (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE);
}

View file

@ -0,0 +1,677 @@
/*
* 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/>.
*/
#define FIXED_PROPS
#define LZMA_BASE_SIZE 1846
#define LZMA_LIT_SIZE 768
#define LZMA_PROPERTIES_SIZE 5
#define kNumTopBits 24
#define kTopValue (1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
#define kNumPosBitsMax 4
#define kNumPosStatesMax (1 << kNumPosBitsMax)
#define kLenNumLowBits 3
#define kLenNumLowSymbols (1 << kLenNumLowBits)
#define kLenNumMidBits 3
#define kLenNumMidSymbols (1 << kLenNumMidBits)
#define kLenNumHighBits 8
#define kLenNumHighSymbols (1 << kLenNumHighBits)
#define LenChoice 0
#define LenChoice2 (LenChoice + 1)
#define LenLow (LenChoice2 + 1)
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
#define kNumStates 12
#define kNumLitStates 7
#define kStartPosModelIndex 4
#define kEndPosModelIndex 14
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
#define kNumPosSlotBits 6
#define kNumLenToPosStates 4
#define kNumAlignBits 4
#define kAlignTableSize (1 << kNumAlignBits)
#define kMatchMinLen 2
#define IsMatch 0
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
#define IsRepG0 (IsRep + kNumStates)
#define IsRepG1 (IsRepG0 + kNumStates)
#define IsRepG2 (IsRepG1 + kNumStates)
#define IsRep0Long (IsRepG2 + kNumStates)
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
#define LenCoder (Align + kAlignTableSize)
#define RepLenCoder (LenCoder + kNumLenProbs)
#define Literal (RepLenCoder + kNumLenProbs)
#if 0
DbgOut:
pushf
pushl %ebp
pushl %edi
pushl %esi
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
call _DebugPrint
popl %eax
popl %ebx
popl %ecx
popl %edx
popl %esi
popl %edi
popl %ebp
popf
ret
/*
* int LzmaDecodeProperties(CLzmaProperties *propsRes,
* const unsigned char *propsData,
* int size);
*/
_LzmaDecodePropertiesA:
movb (%edx), %dl
xorl %ecx, %ecx
1:
cmpb $45, %dl
jb 2f
incl %ecx
subb $45, %dl
jmp 1b
2:
movl %ecx, 8(%eax) /* pb */
xorl %ecx, %ecx
1:
cmpb $9, %dl
jb 2f
incl %ecx
subb $9, %dl
2:
movl %ecx, 4(%eax) /* lp */
movb %dl, %cl
movl %ecx, (%eax) /* lc */
#endif
#ifndef ASM_FILE
xorl %eax, %eax
#endif
ret
#define out_size 8(%ebp)
#define now_pos -4(%ebp)
#define prev_byte -8(%ebp)
#define range -12(%ebp)
#define code -16(%ebp)
#define state -20(%ebp)
#define rep0 -24(%ebp)
#define rep1 -28(%ebp)
#define rep2 -32(%ebp)
#define rep3 -36(%ebp)
#ifdef FIXED_PROPS
#define FIXED_LC 3
#define FIXED_LP 0
#define FIXED_PB 2
#define POS_STATE_MASK ((1 << (FIXED_PB)) - 1)
#define LIT_POS_MASK ((1 << (FIXED_LP)) - 1)
#define LOCAL_SIZE 36
#else
#define lc (%ebx)
#define lp 4(%ebx)
#define pb 8(%ebx)
#define probs 12(%ebx)
#define pos_state_mask -40(%ebp)
#define lit_pos_mask -44(%ebp)
#define LOCAL_SIZE 44
#endif
RangeDecoderBitDecode:
#ifdef FIXED_PROPS
leal (%ebx, %eax, 4), %eax
#else
shll $2, %eax
addl probs, %eax
#endif
movl %eax, %ecx
movl (%ecx), %eax
movl range, %edx
shrl $kNumBitModelTotalBits, %edx
mull %edx
cmpl code, %eax
jbe 1f
movl %eax, range
movl $kBitModelTotal, %edx
subl (%ecx), %edx
shrl $kNumMoveBits, %edx
addl %edx, (%ecx)
clc
3:
pushf
cmpl $kTopValue, range
jnc 2f
shll $8, code
lodsb
movb %al, code
shll $8, range
2:
popf
ret
1:
subl %eax, range
subl %eax, code
movl (%ecx), %edx
shrl $kNumMoveBits, %edx
subl %edx, (%ecx)
stc
jmp 3b
RangeDecoderBitTreeDecode:
RangeDecoderReverseBitTreeDecode:
movzbl %cl, %ecx
xorl %edx, %edx
pushl %edx
incl %edx
pushl %edx
1:
pushl %eax
pushl %ecx
pushl %edx
addl %edx, %eax
call RangeDecoderBitDecode
popl %edx
popl %ecx
jnc 2f
movl 4(%esp), %eax
orl %eax, 8(%esp)
stc
2:
adcl %edx, %edx
popl %eax
shll $1, (%esp)
loop 1b
popl %ecx
subl %ecx, %edx /* RangeDecoderBitTreeDecode */
popl %ecx /* RangeDecoderReverseBitTreeDecode */
ret
LzmaLenDecode:
pushl %eax
addl $LenChoice, %eax
call RangeDecoderBitDecode
popl %eax
jc 1f
pushl $0
movb $kLenNumLowBits, %cl
addl $LenLow, %eax
2:
movl 12(%esp), %edx
shll %cl, %edx
addl %edx, %eax
3:
call RangeDecoderBitTreeDecode
popl %eax
addl %eax, %edx
ret
1:
pushl %eax
addl $LenChoice2, %eax
call RangeDecoderBitDecode
popl %eax
jc 1f
pushl $kLenNumLowSymbols
movb $kLenNumMidBits, %cl
addl $LenMid, %eax
jmp 2b
1:
pushl $(kLenNumLowSymbols + kLenNumMidSymbols)
addl $LenHigh, %eax
movb $kLenNumHighBits, %cl
jmp 3b
WriteByte:
movb %al, prev_byte
stosb
incl now_pos
ret
/*
* int LzmaDecode(CLzmaDecoderState *vs,
* const unsigned char *inStream,
* unsigned char *outStream,
* SizeT outSize);
*/
_LzmaDecodeA:
pushl %ebp
movl %esp, %ebp
subl $LOCAL_SIZE, %esp
#ifndef ASM_FILE
pushl %esi
pushl %edi
pushl %ebx
movl %eax, %ebx
movl %edx, %esi
pushl %ecx
#else
pushl %edi
#endif
cld
#ifdef FIXED_PROPS
movl %ebx, %edi
movl $(Literal + (LZMA_LIT_SIZE << (FIXED_LC + FIXED_LP))), %ecx
#else
movl $LZMA_LIT_SIZE, %eax
movb lc, %cl
addb lp, %cl
shll %cl, %eax
addl $Literal, %eax
movl %eax, %ecx
movl probs, %edi
#endif
movl $(kBitModelTotal >> 1), %eax
rep
stosl
popl %edi
xorl %eax, %eax
movl %eax, now_pos
movl %eax, prev_byte
movl %eax, state
incl %eax
movl %eax, rep0
movl %eax, rep1
movl %eax, rep2
movl %eax, rep3
#ifndef FIXED_PROPS
movl %eax, %edx
movb pb, %cl
shll %cl, %edx
decl %edx
movl %edx, pos_state_mask
movl %eax, %edx
movb lp, %cl
shll %cl, %edx
decl %edx
movl %edx, lit_pos_mask;
#endif
/* RangeDecoderInit */
negl %eax
movl %eax, range
incl %eax
movb $5, %cl
1:
shll $8, %eax
lodsb
loop 1b
movl %eax, code
lzma_decode_loop:
movl now_pos, %eax
cmpl out_size, %eax
jb 1f
#ifndef ASM_FILE
xorl %eax, %eax
popl %ebx
popl %edi
popl %esi
#endif
movl %ebp, %esp
popl %ebp
ret
1:
#ifdef FIXED_PROPS
andl $POS_STATE_MASK, %eax
#else
andl pos_state_mask, %eax
#endif
pushl %eax /* posState */
movl state, %edx
shll $kNumPosBitsMax, %edx
addl %edx, %eax
pushl %eax /* (state << kNumPosBitsMax) + posState */
call RangeDecoderBitDecode
jc 1f
movl now_pos, %eax
#ifdef FIXED_PROPS
andl $LIT_POS_MASK, %eax
shll $FIXED_LC, %eax
movl prev_byte, %edx
shrl $(8 - FIXED_LC), %edx
#else
andl lit_pos_mask, %eax
movb lc, %cl
shll %cl, %eax
negb %cl
addb $8, %cl
movl prev_byte, %edx
shrl %cl, %edx
#endif
addl %edx, %eax
movl $LZMA_LIT_SIZE, %edx
mull %edx
addl $Literal, %eax
pushl %eax
incl %edx /* edx = 1 */
movl rep0, %eax
negl %eax
pushl (%edi, %eax) /* matchByte */
cmpb $kNumLitStates, state
jb 5f
/* LzmaLiteralDecodeMatch */
3:
cmpl $0x100, %edx
jae 4f
xorl %eax, %eax
shlb $1, (%esp)
adcl %eax, %eax
pushl %eax
pushl %edx
shll $8, %eax
leal 0x100(%edx, %eax), %eax
addl 12(%esp), %eax
call RangeDecoderBitDecode
setc %al
popl %edx
adcl %edx, %edx
popl %ecx
cmpb %cl, %al
jz 3b
5:
/* LzmaLiteralDecode */
cmpl $0x100, %edx
jae 4f
pushl %edx
movl %edx, %eax
addl 8(%esp), %eax
call RangeDecoderBitDecode
popl %edx
adcl %edx, %edx
jmp 5b
4:
addl $16, %esp
movb %dl, %al
call WriteByte
movb state, %al
cmpb $4, %al
jae 2f
xorb %al, %al
jmp 3f
2:
subb $3, %al
cmpb $7, %al
jb 3f
subb $3, %al
3:
movb %al, state
jmp lzma_decode_loop
1:
movl state, %eax
addl $IsRep, %eax
call RangeDecoderBitDecode
jnc 1f
movl state, %eax
addl $IsRepG0, %eax
call RangeDecoderBitDecode
jc 10f
movl (%esp), %eax
addl $IsRep0Long, %eax
call RangeDecoderBitDecode
jc 20f
cmpb $7, state
movb $9, state
jb 100f
addb $2, state
100:
movl $1, %ecx
3:
movl rep0, %edx
negl %edx
4:
movb (%edi, %edx), %al
call WriteByte
loop 4b
popl %eax
popl %eax
jmp lzma_decode_loop
10:
movl state, %eax
addl $IsRepG1, %eax
call RangeDecoderBitDecode
movl rep1, %edx
jnc 100f
movl state, %eax
addl $IsRepG2, %eax
call RangeDecoderBitDecode
movl rep2, %edx
jnc 1000f
movl rep2, %edx
xchgl rep3, %edx
1000:
pushl rep1
popl rep2
100:
xchg rep0, %edx
movl %edx, rep1
20:
movl $RepLenCoder, %eax
call LzmaLenDecode
cmpb $7, state
movb $8, state
jb 100f
addb $3, state
100:
jmp 2f
1:
movl rep0, %eax
xchgl rep1, %eax
xchgl rep2, %eax
movl %eax, rep3
cmpb $7, state
movb $7, state
jb 10f
addb $3, state
10:
movl $LenCoder, %eax
call LzmaLenDecode
pushl %edx
movl $(kNumLenToPosStates - 1), %eax
cmpl %eax, %edx
jbe 100f
movl %eax, %edx
100:
movb $kNumPosSlotBits, %cl
shll %cl, %edx
leal PosSlot(%edx), %eax
call RangeDecoderBitTreeDecode
movl %edx, rep0
cmpl $kStartPosModelIndex, %edx
jb 100f
movl %edx, %ecx
shrl $1, %ecx
decl %ecx
movzbl %dl, %eax
andb $1, %al
orb $2, %al
shll %cl, %eax
movl %eax, rep0
cmpl $kEndPosModelIndex, %edx
jae 200f
movl rep0, %eax
addl $(SpecPos - 1), %eax
subl %edx, %eax
jmp 300f
200:
subb $kNumAlignBits, %cl
/* RangeDecoderDecodeDirectBits */
xorl %edx, %edx
1000:
shrl $1, range
shll $1, %edx
movl range, %eax
cmpl %eax, code
jb 2000f
subl %eax, code
orb $1, %dl
2000:
cmpl $kTopValue, %eax
jae 3000f
shll $8, range
shll $8, code
lodsb
movb %al, code
3000:
loop 1000b
movb $kNumAlignBits, %cl
shll %cl, %edx
addl %edx, rep0
movl $Align, %eax
300:
call RangeDecoderReverseBitTreeDecode
addl %ecx, rep0
100:
incl rep0
popl %edx
2:
addl $kMatchMinLen, %edx
movl %edx, %ecx
jmp 3b

View file

@ -0,0 +1,68 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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 <http://www.gnu.org/licenses/>.
*/
#include <grub/machine/init.h>
#include <grub/machine/memory.h>
#include <grub/err.h>
#include <grub/types.h>
#include <grub/misc.h>
grub_err_t
grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
{
grub_uint32_t cont;
struct grub_machine_mmap_entry *entry
= (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
grub_memset (entry, 0, sizeof (entry));
/* Check if grub_get_mmap_entry works. */
cont = grub_get_mmap_entry (entry, 0);
if (entry->size)
do
{
if (hook (entry->addr, entry->len,
/* Multiboot mmaps have been defined to match with the E820 definition.
Therefore, we can just pass type through. */
entry->type))
break;
if (! cont)
break;
grub_memset (entry, 0, sizeof (entry));
cont = grub_get_mmap_entry (entry, cont);
}
while (entry->size);
else
{
grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
if (eisa_mmap)
{
if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, GRUB_MACHINE_MEMORY_AVAILABLE) == 0)
hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MACHINE_MEMORY_AVAILABLE);
}
else
hook (0x100000, grub_get_memsize (1) << 10, GRUB_MACHINE_MEMORY_AVAILABLE);
}
return 0;
}

File diff suppressed because it is too large Load diff

56
grub-core/kern/i386/pit.c Normal file
View file

@ -0,0 +1,56 @@
/*
* 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/i386/io.h>
#include <grub/i386/pit.h>
#define TIMER2_REG_CONTROL 0x42
#define TIMER_REG_COMMAND 0x43
#define TIMER2_REG_LATCH 0x61
#define TIMER2_SELECT 0x80
#define TIMER_ENABLE_LSB 0x20
#define TIMER_ENABLE_MSB 0x10
#define TIMER2_LATCH 0x20
#define TIMER2_SPEAKER 0x02
#define TIMER2_GATE 0x01
void
grub_pit_wait (grub_uint16_t tics)
{
/* Disable timer2 gate and speaker. */
grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE),
TIMER2_REG_LATCH);
/* Set tics. */
grub_outb (TIMER2_SELECT | TIMER_ENABLE_LSB | TIMER_ENABLE_MSB, TIMER_REG_COMMAND);
grub_outb (tics & 0xff, TIMER2_REG_CONTROL);
grub_outb (tics >> 8, TIMER2_REG_CONTROL);
/* Enable timer2 gate, keep speaker disabled. */
grub_outb ((grub_inb (TIMER2_REG_LATCH) & ~ TIMER2_SPEAKER) | TIMER2_GATE,
TIMER2_REG_LATCH);
/* Wait. */
while ((grub_inb (TIMER2_REG_LATCH) & TIMER2_LATCH) == 0x00);
/* Disable timer2 gate and speaker. */
grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE),
TIMER2_REG_LATCH);
}

View file

@ -0,0 +1,147 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2010 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/pci.h>
#include <grub/machine/kernel.h>
#include <grub/misc.h>
#include <grub/vga.h>
static struct {grub_uint8_t r, g, b, a; } colors[] =
{
// {R, G, B, A}
{0x00, 0x00, 0x00, 0xFF}, // 0 = black
{0x00, 0x00, 0xA8, 0xFF}, // 1 = blue
{0x00, 0xA8, 0x00, 0xFF}, // 2 = green
{0x00, 0xA8, 0xA8, 0xFF}, // 3 = cyan
{0xA8, 0x00, 0x00, 0xFF}, // 4 = red
{0xA8, 0x00, 0xA8, 0xFF}, // 5 = magenta
{0xA8, 0x54, 0x00, 0xFF}, // 6 = brown
{0xA8, 0xA8, 0xA8, 0xFF}, // 7 = light gray
{0x54, 0x54, 0x54, 0xFF}, // 8 = dark gray
{0x54, 0x54, 0xFE, 0xFF}, // 9 = bright blue
{0x54, 0xFE, 0x54, 0xFF}, // 10 = bright green
{0x54, 0xFE, 0xFE, 0xFF}, // 11 = bright cyan
{0xFE, 0x54, 0x54, 0xFF}, // 12 = bright red
{0xFE, 0x54, 0xFE, 0xFF}, // 13 = bright magenta
{0xFE, 0xFE, 0x54, 0xFF}, // 14 = yellow
{0xFE, 0xFE, 0xFE, 0xFF} // 15 = white
};
#include <ascii.h>
static void
load_font (void)
{
unsigned i;
grub_vga_gr_write (0 << 2, GRUB_VGA_GR_GR6);
grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE);
grub_vga_sr_write (1 << GRUB_VGA_TEXT_FONT_PLANE,
GRUB_VGA_SR_MAP_MASK_REGISTER);
grub_vga_gr_write (0, GRUB_VGA_GR_DATA_ROTATE);
grub_vga_gr_write (0, GRUB_VGA_GR_MODE);
grub_vga_gr_write (0xff, GRUB_VGA_GR_BITMASK);
for (i = 0; i < 128; i++)
grub_memcpy ((void *) (0xa0000 + 32 * i), ascii_bitmaps + 16 * i, 16);
}
static void
load_palette (void)
{
unsigned i;
for (i = 0; i < 16; i++)
grub_vga_write_arx (i, i);
for (i = 0; i < ARRAY_SIZE (colors); i++)
grub_vga_palette_write (i, colors[i].r, colors[i].g, colors[i].b);
}
void
grub_qemu_init_cirrus (void)
{
auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid);
int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)))
{
grub_pci_address_t addr;
grub_uint32_t class;
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
class = grub_pci_read (addr);
if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA)
return 0;
/* FIXME: chooose addresses dynamically. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
grub_pci_write (addr, 0xf0000000 | GRUB_PCI_ADDR_MEM_PREFETCH
| GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32);
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
grub_pci_write (addr, 0xf2000000
| GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32);
addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
grub_pci_write (addr, GRUB_PCI_COMMAND_MEM_ENABLED
| GRUB_PCI_COMMAND_IO_ENABLED);
return 1;
}
grub_pci_iterate (find_card);
grub_outb (GRUB_VGA_IO_MISC_COLOR, GRUB_VGA_IO_MISC_WRITE);
load_font ();
grub_vga_gr_write (GRUB_VGA_GR_GR6_MMAP_CGA, GRUB_VGA_GR_GR6);
grub_vga_gr_write (GRUB_VGA_GR_MODE_ODD_EVEN, GRUB_VGA_GR_MODE);
grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE);
grub_vga_sr_write ((1 << GRUB_VGA_TEXT_TEXT_PLANE)
| (1 << GRUB_VGA_TEXT_ATTR_PLANE),
GRUB_VGA_SR_MAP_MASK_REGISTER);
grub_vga_cr_write (15, GRUB_VGA_CR_CELL_HEIGHT);
grub_vga_cr_write (79, GRUB_VGA_CR_HORIZ_END);
grub_vga_cr_write (40, GRUB_VGA_CR_PITCH);
int vert = 25 * 16;
grub_vga_cr_write (vert & 0xff, GRUB_VGA_CR_VDISPLAY_END);
grub_vga_cr_write (((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT)
& GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK)
| ((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT)
& GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK),
GRUB_VGA_CR_OVERFLOW);
load_palette ();
grub_vga_write_arx (GRUB_VGA_ARX_MODE_TEXT, GRUB_VGA_ARX_MODE);
grub_vga_write_arx (0, GRUB_VGA_ARX_COLOR_SELECT);
grub_vga_sr_write (GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK,
GRUB_VGA_SR_CLOCKING_MODE);
grub_vga_cr_write (14, GRUB_VGA_CR_CURSOR_START);
grub_vga_cr_write (15, GRUB_VGA_CR_CURSOR_END);
grub_outb (0x20, 0x3c0);
}

View file

@ -0,0 +1,99 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 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/machine/init.h>
#include <grub/machine/memory.h>
#include <grub/machine/boot.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/cmos.h>
#define QEMU_CMOS_MEMSIZE_HIGH 0x35
#define QEMU_CMOS_MEMSIZE_LOW 0x34
#define QEMU_CMOS_MEMSIZE2_HIGH 0x31
#define QEMU_CMOS_MEMSIZE2_LOW 0x30
#define min(a,b) ((a) > (b) ? (b) : (a))
extern char _start[];
extern char _end[];
static grub_uint64_t mem_size, above_4g;
void
grub_machine_mmap_init ()
{
mem_size = ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH)) << 24
| ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW)) << 16;
if (mem_size > 0)
{
/* Don't ask... */
mem_size += (16 * 1024 * 1024);
}
else
{
mem_size
= ((((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE2_HIGH)) << 18)
| ((grub_uint64_t) (grub_cmos_read (QEMU_CMOS_MEMSIZE2_LOW)) << 10))
+ 1024 * 1024;
}
above_4g = (((grub_uint64_t) grub_cmos_read (0x5b)) << 16)
| (((grub_uint64_t) grub_cmos_read (0x5c)) << 24)
| (((grub_uint64_t) grub_cmos_read (0x5d)) << 32);
}
grub_err_t
grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
{
if (hook (0x0,
(grub_addr_t) _start,
GRUB_MACHINE_MEMORY_AVAILABLE))
return 1;
if (hook ((grub_addr_t) _end,
0xa0000 - (grub_addr_t) _end,
GRUB_MACHINE_MEMORY_AVAILABLE))
return 1;
if (hook (GRUB_MEMORY_MACHINE_UPPER,
0x100000 - GRUB_MEMORY_MACHINE_UPPER,
GRUB_MACHINE_MEMORY_RESERVED))
return 1;
/* Everything else is free. */
if (hook (0x100000,
min (mem_size, (grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE) - 0x100000,
GRUB_MACHINE_MEMORY_AVAILABLE))
return 1;
/* Protect boot.img, which contains the gdt. It is mapped at the top of memory
(it is also mapped below 0x100000, but we already reserved that area). */
if (hook ((grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE,
GRUB_BOOT_MACHINE_SIZE,
GRUB_MACHINE_MEMORY_RESERVED))
return 1;
if (above_4g != 0 && hook (0x100000000ULL, above_4g,
GRUB_MACHINE_MEMORY_AVAILABLE))
return 1;
return 0;
}

View file

@ -0,0 +1,99 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009 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 <config.h>
#include <grub/symbol.h>
#include <grub/machine/memory.h>
#include <grub/machine/kernel.h>
.text
.code32
.globl _start
_start:
jmp codestart
. = _start + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR
VARIABLE(grub_core_entry_addr)
.long 0
VARIABLE(grub_kernel_image_size)
.long 0
VARIABLE(grub_prefix)
/* to be filled by grub-mkimage */
/*
* Leave some breathing room for the prefix.
*/
. = _start + GRUB_KERNEL_MACHINE_DATA_END
codestart:
/* Relocate to low memory. First we figure out our location.
We will derive the rom start address from it. */
call 1f
1: popl %esi
/* Rom size is a multiple of 64 kiB. With this we get the
value of `grub_core_entry_addr' in %esi. */
xorw %si, %si
/* ... which allows us to access `grub_kernel_image_size'
before relocation. */
movl (grub_kernel_image_size - _start)(%esi), %ecx
movl $_start, %edi
cld
rep
movsb
ljmp $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $1f
1:
#ifdef APPLE_CC
/* clean out the bss */
bss_start_abs = ABS (bss_start)
bss_end_abs = ABS (bss_end)
movl bss_start_abs, %edi
/* compute the bss length */
movl bss_end_abs, %ecx
subl %edi, %ecx
#else
/* clean out the bss */
movl $BSS_START_SYMBOL, %edi
/* compute the bss length */
movl $END_SYMBOL, %ecx
subl %edi, %ecx
#endif
/* clean out */
xorl %eax, %eax
cld
rep
stosb
/*
* Call the start of main body of C code.
*/
call EXT_C(grub_main)
/* This should never happen. */
jmp EXT_C(grub_stop)
#include "../realmode.S"

View file

@ -0,0 +1,242 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2009,2010 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/i386/pc/memory.h>
/*
* Note: These functions defined in this file may be called from C.
* Be careful of that you must not modify some registers. Quote
* from gcc-2.95.2/gcc/config/i386/i386.h:
1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
registers that can be used without being saved.
The latter must include the registers where values are returned
and the register where structure-value addresses are passed.
Aside from that, you can include as many other registers as you like.
ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg
{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
*/
/*
* Note: GRUB is compiled with the options -mrtd and -mregparm=3.
* So the first three arguments are passed in %eax, %edx, and %ecx,
* respectively, and if a function has a fixed number of arguments
* and the number if greater than three, the function must return
* with "ret $N" where N is ((the number of arguments) - 3) * 4.
*/
/*
* This is the area for all of the special variables.
*/
.p2align 2 /* force 4-byte alignment */
protstack:
.long GRUB_MEMORY_MACHINE_PROT_STACK
/*
* This is the Global Descriptor Table
*
* An entry, a "Segment Descriptor", looks like this:
*
* 31 24 19 16 7 0
* ------------------------------------------------------------
* | | |B| |A| | | |1|0|E|W|A| |
* | BASE 31..24 |G|/|L|V| LIMIT |P|DPL| TYPE | BASE 23:16 | 4
* | | |D| |L| 19..16| | |1|1|C|R|A| |
* ------------------------------------------------------------
* | | |
* | BASE 15..0 | LIMIT 15..0 | 0
* | | |
* ------------------------------------------------------------
*
* Note the ordering of the data items is reversed from the above
* description.
*/
.p2align 2 /* force 4-byte alignment */
gdt:
.word 0, 0
.byte 0, 0, 0, 0
/* -- code segment --
* base = 0x00000000, limit = 0xFFFFF (4 KiB Granularity), present
* type = 32bit code execute/read, DPL = 0
*/
.word 0xFFFF, 0
.byte 0, 0x9A, 0xCF, 0
/* -- data segment --
* base = 0x00000000, limit 0xFFFFF (4 KiB Granularity), present
* type = 32 bit data read/write, DPL = 0
*/
.word 0xFFFF, 0
.byte 0, 0x92, 0xCF, 0
/* -- 16 bit real mode CS --
* base = 0x00000000, limit 0x0FFFF (1 B Granularity), present
* type = 16 bit code execute/read only/conforming, DPL = 0
*/
.word 0xFFFF, 0
.byte 0, 0x9E, 0, 0
/* -- 16 bit real mode DS --
* base = 0x00000000, limit 0x0FFFF (1 B Granularity), present
* type = 16 bit data read/write, DPL = 0
*/
.word 0xFFFF, 0
.byte 0, 0x92, 0, 0
/* this is the GDT descriptor */
gdtdesc:
.word 0x27 /* limit */
.long gdt /* addr */
/*
* These next two routines, "real_to_prot" and "prot_to_real" are structured
* in a very specific way. Be very careful when changing them.
*
* NOTE: Use of either one messes up %eax and %ebp.
*/
real_to_prot:
.code16
cli
/* load the GDT register */
xorw %ax, %ax
movw %ax, %ds
DATA32 ADDR32 lgdt gdtdesc
/* turn on protected mode */
movl %cr0, %eax
orl $GRUB_MEMORY_CPU_CR0_PE_ON, %eax
movl %eax, %cr0
/* jump to relocation, flush prefetch queue, and reload %cs */
DATA32 ljmp $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg
.code32
protcseg:
/* reload other segment registers */
movw $GRUB_MEMORY_MACHINE_PROT_MODE_DSEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
/* put the return address in a known safe location */
movl (%esp), %eax
movl %eax, GRUB_MEMORY_MACHINE_REAL_STACK
/* get protected mode stack */
movl protstack, %eax
movl %eax, %esp
movl %eax, %ebp
/* get return address onto the right stack */
movl GRUB_MEMORY_MACHINE_REAL_STACK, %eax
movl %eax, (%esp)
/* zero %eax */
xorl %eax, %eax
/* return on the old (or initialized) stack! */
ret
prot_to_real:
/* just in case, set GDT */
lgdt gdtdesc
/* save the protected mode stack */
movl %esp, %eax
movl %eax, protstack
/* get the return address */
movl (%esp), %eax
movl %eax, GRUB_MEMORY_MACHINE_REAL_STACK
/* set up new stack */
movl $GRUB_MEMORY_MACHINE_REAL_STACK, %eax
movl %eax, %esp
movl %eax, %ebp
/* set up segment limits */
movw $GRUB_MEMORY_MACHINE_PSEUDO_REAL_DSEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
/* this might be an extra step */
/* jump to a 16 bit segment */
ljmp $GRUB_MEMORY_MACHINE_PSEUDO_REAL_CSEG, $tmpcseg
tmpcseg:
.code16
/* clear the PE bit of CR0 */
movl %cr0, %eax
andl $(~GRUB_MEMORY_CPU_CR0_PE_ON), %eax
movl %eax, %cr0
/* flush prefetch queue, reload %cs */
DATA32 ljmp $0, $realcseg
realcseg:
/* we are in real mode now
* set up the real mode segment registers : DS, SS, ES
*/
/* zero %eax */
xorl %eax, %eax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
#ifdef GRUB_MACHINE_PCBIOS
/* restore interrupts */
sti
#endif
/* return on new stack! */
DATA32 ret
.code32
/*
* grub_reboot()
*
* Reboot the system. At the moment, rely on BIOS.
*/
FUNCTION(grub_reboot)
call prot_to_real
.code16
cold_reboot:
/* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */
movw $0x0472, %di
movw %ax, (%di)
ljmp $0xf000, $0xfff0
.code32

74
grub-core/kern/i386/tsc.c Normal file
View file

@ -0,0 +1,74 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/time.h>
#include <grub/misc.h>
#include <grub/i386/tsc.h>
#include <grub/i386/pit.h>
/* This defines the value TSC had at the epoch (that is, when we calibrated it). */
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 calibrate the TSC rate (relative, not absolute time). */
grub_uint64_t start_tsc;
grub_uint64_t end_tsc;
start_tsc = grub_get_tsc ();
grub_pit_wait (0xffff);
end_tsc = grub_get_tsc ();
tsc_ticks_per_ms = grub_divmod64 (end_tsc - start_tsc, 55, 0);
}
void
grub_tsc_init (void)
{
if (grub_cpu_is_tsc_supported ())
{
tsc_boot_time = grub_get_tsc ();
calibrate_tsc ();
grub_install_get_time_ms (grub_tsc_get_time_ms);
}
else
{
grub_install_get_time_ms (grub_rtc_get_time_ms);
}
}