Merge mainline into mbivid
This commit is contained in:
commit
9ba27423f5
931 changed files with 122070 additions and 40781 deletions
129
grub-core/kern/i386/coreboot/init.c
Normal file
129
grub-core/kern/i386/coreboot/init.c
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* 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/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/floppy.h>
|
||||
#include <grub/cpu/tsc.h>
|
||||
#ifdef GRUB_MACHINE_QEMU
|
||||
#include <grub/machine/kernel.h>
|
||||
#endif
|
||||
|
||||
extern char _start[];
|
||||
extern char _end[];
|
||||
|
||||
grub_uint32_t
|
||||
grub_get_rtc (void)
|
||||
{
|
||||
grub_fatal ("grub_get_rtc() is not implemented.\n");
|
||||
}
|
||||
|
||||
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
|
||||
}
|
107
grub-core/kern/i386/coreboot/mmap.c
Normal file
107
grub-core/kern/i386/coreboot/mmap.c
Normal 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;
|
||||
}
|
87
grub-core/kern/i386/coreboot/startup.S
Normal file
87
grub-core/kern/i386/coreboot/startup.S
Normal 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_PREFIX_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
109
grub-core/kern/i386/dl.c
Normal 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;
|
||||
}
|
47
grub-core/kern/i386/efi/init.c
Normal file
47
grub-core/kern/i386/efi/init.c
Normal 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 ();
|
||||
}
|
66
grub-core/kern/i386/efi/startup.S
Normal file
66
grub-core/kern/i386/efi/startup.S
Normal 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"
|
34
grub-core/kern/i386/ieee1275/init.c
Normal file
34
grub-core/kern/i386/ieee1275/init.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* 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)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
grub_arch_sync_caches (void *address __attribute__ ((unused)),
|
||||
grub_size_t len __attribute__ ((unused)))
|
||||
{
|
||||
}
|
65
grub-core/kern/i386/ieee1275/startup.S
Normal file
65
grub-core/kern/i386/ieee1275/startup.S
Normal 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_PREFIX_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"
|
||||
|
120
grub-core/kern/i386/loader.S
Normal file
120
grub-core/kern/i386/loader.S
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
/*
|
||||
* void grub_linux_boot_zimage (void)
|
||||
*/
|
||||
VARIABLE(grub_linux_prot_size)
|
||||
.long 0
|
||||
VARIABLE(grub_linux_tmp_addr)
|
||||
.long 0
|
||||
VARIABLE(grub_linux_real_addr)
|
||||
.long 0
|
||||
VARIABLE(grub_linux_is_bzimage)
|
||||
.long 0
|
||||
|
||||
FUNCTION(grub_linux16_real_boot)
|
||||
/* Must be done before zImage copy. */
|
||||
call EXT_C(grub_dl_unload_all)
|
||||
|
||||
movl EXT_C(grub_linux_is_bzimage), %ebx
|
||||
test %ebx, %ebx
|
||||
jne bzimage
|
||||
|
||||
/* copy the kernel */
|
||||
movl EXT_C(grub_linux_prot_size), %ecx
|
||||
addl $3, %ecx
|
||||
shrl $2, %ecx
|
||||
movl $GRUB_LINUX_BZIMAGE_ADDR, %esi
|
||||
movl $GRUB_LINUX_ZIMAGE_ADDR, %edi
|
||||
cld
|
||||
rep
|
||||
movsl
|
||||
|
||||
bzimage:
|
||||
movl EXT_C(grub_linux_real_addr), %ebx
|
||||
|
||||
/* copy the real mode code */
|
||||
movl EXT_C(grub_linux_tmp_addr), %esi
|
||||
movl %ebx, %edi
|
||||
movl $GRUB_LINUX_SETUP_MOVE_SIZE, %ecx
|
||||
cld
|
||||
rep
|
||||
movsb
|
||||
|
||||
/* change %ebx to the segment address */
|
||||
shrl $4, %ebx
|
||||
movl %ebx, %eax
|
||||
addl $0x20, %eax
|
||||
movw %ax, linux_setup_seg
|
||||
|
||||
/* XXX new stack pointer in safe area for calling functions */
|
||||
movl $0x4000, %esp
|
||||
call EXT_C(grub_stop_floppy)
|
||||
|
||||
/* final setup for linux boot */
|
||||
call prot_to_real
|
||||
.code16
|
||||
|
||||
cli
|
||||
movw %bx, %ss
|
||||
movw $GRUB_LINUX_SETUP_STACK, %sp
|
||||
|
||||
movw %bx, %ds
|
||||
movw %bx, %es
|
||||
movw %bx, %fs
|
||||
movw %bx, %gs
|
||||
|
||||
/* ljmp */
|
||||
.byte 0xea
|
||||
.word 0
|
||||
linux_setup_seg:
|
||||
.word 0
|
||||
.code32
|
||||
|
29
grub-core/kern/i386/misc.S
Normal file
29
grub-core/kern/i386/misc.S
Normal 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
|
86
grub-core/kern/i386/multiboot_mmap.c
Normal file
86
grub-core/kern/i386/multiboot_mmap.c
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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/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;
|
||||
}
|
241
grub-core/kern/i386/pc/init.c
Normal file
241
grub-core/kern/i386/pc/init.c
Normal file
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* 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/i386/floppy.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/console.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <grub/machine/int.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--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* grub_get_conv_memsize(i) : return the conventional memory size in KB.
|
||||
* BIOS call "INT 12H" to get conventional memory size
|
||||
* The return value in AX.
|
||||
*/
|
||||
static inline grub_uint16_t
|
||||
grub_get_conv_memsize (void)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
grub_bios_interrupt (0x12, ®s);
|
||||
return regs.eax & 0xffff;
|
||||
}
|
||||
|
||||
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_conv_memsize () << 10;
|
||||
|
||||
/* Sanity check. */
|
||||
if (grub_lower_mem < GRUB_MEMORY_MACHINE_RESERVED_END)
|
||||
grub_fatal ("too small memory");
|
||||
|
||||
/* 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);
|
||||
}
|
677
grub-core/kern/i386/pc/lzma_decode.S
Normal file
677
grub-core/kern/i386/pc/lzma_decode.S
Normal 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
|
154
grub-core/kern/i386/pc/mmap.c
Normal file
154
grub-core/kern/i386/pc/mmap.c
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* 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/memory.h>
|
||||
#include <grub/machine/int.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
/*
|
||||
* grub_get_ext_memsize() : return the extended memory size in KB.
|
||||
* BIOS call "INT 15H, AH=88H" to get extended memory size
|
||||
* The return value in AX.
|
||||
*
|
||||
*/
|
||||
static inline grub_uint16_t
|
||||
grub_get_ext_memsize (void)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
|
||||
regs.eax = 0x8800;
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
grub_bios_interrupt (0x15, ®s);
|
||||
return regs.eax & 0xffff;
|
||||
}
|
||||
|
||||
/* Get a packed EISA memory map. Lower 16 bits are between 1MB and 16MB
|
||||
in 1KB parts, and upper 16 bits are above 16MB in 64KB parts. If error, return zero.
|
||||
BIOS call "INT 15H, AH=E801H" to get EISA memory map,
|
||||
AX = memory between 1M and 16M in 1K parts.
|
||||
BX = memory above 16M in 64K parts.
|
||||
*/
|
||||
|
||||
static inline grub_uint32_t
|
||||
grub_get_eisa_mmap (void)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
regs.eax = 0xe801;
|
||||
grub_bios_interrupt (0x15, ®s);
|
||||
|
||||
if ((regs.eax & 0xff00) == 0x8600)
|
||||
return 0;
|
||||
|
||||
return (regs.eax & 0xffff) | (regs.ebx << 16);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* grub_get_mmap_entry(addr, cont) : address and old continuation value (zero to
|
||||
* start), for the Query System Address Map BIOS call.
|
||||
*
|
||||
* Sets the first 4-byte int value of "addr" to the size returned by
|
||||
* the call. If the call fails, sets it to zero.
|
||||
*
|
||||
* Returns: new (non-zero) continuation value, 0 if done.
|
||||
*/
|
||||
/* Get a memory map entry. Return next continuation value. Zero means
|
||||
the end. */
|
||||
static grub_uint32_t
|
||||
grub_get_mmap_entry (struct grub_machine_mmap_entry *entry,
|
||||
grub_uint32_t cont)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
|
||||
/* place address (+4) in ES:DI */
|
||||
regs.es = ((grub_addr_t) &entry->addr) >> 4;
|
||||
regs.edi = ((grub_addr_t) &entry->addr) & 0xf;
|
||||
|
||||
/* set continuation value */
|
||||
regs.ebx = cont;
|
||||
|
||||
/* set default maximum buffer size */
|
||||
regs.ecx = sizeof (*entry) - sizeof (entry->size);
|
||||
|
||||
/* set EDX to 'SMAP' */
|
||||
regs.edx = 0x534d4150;
|
||||
|
||||
regs.eax = 0xe820;
|
||||
grub_bios_interrupt (0x15, ®s);
|
||||
|
||||
/* write length of buffer (zero if error) into ADDR */
|
||||
if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) || regs.eax != 0x534d4150
|
||||
|| regs.ecx < 0x14 || regs.ecx > 0x400)
|
||||
entry->size = 0;
|
||||
else
|
||||
entry->size = regs.ecx;
|
||||
|
||||
/* return the continuation value */
|
||||
return regs.ebx;
|
||||
}
|
||||
|
||||
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_ext_memsize () << 10, GRUB_MACHINE_MEMORY_AVAILABLE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
1040
grub-core/kern/i386/pc/startup.S
Normal file
1040
grub-core/kern/i386/pc/startup.S
Normal file
File diff suppressed because it is too large
Load diff
56
grub-core/kern/i386/pit.c
Normal file
56
grub-core/kern/i386/pit.c
Normal 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);
|
||||
}
|
147
grub-core/kern/i386/qemu/init.c
Normal file
147
grub-core/kern/i386/qemu/init.c
Normal 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);
|
||||
}
|
98
grub-core/kern/i386/qemu/mmap.c
Normal file
98
grub-core/kern/i386/qemu/mmap.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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/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;
|
||||
}
|
102
grub-core/kern/i386/qemu/startup.S
Normal file
102
grub-core/kern/i386/qemu/startup.S
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* 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_PREFIX_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. */
|
||||
cli
|
||||
1:
|
||||
hlt
|
||||
jmp 1b
|
||||
|
||||
#include "../realmode.S"
|
242
grub-core/kern/i386/realmode.S
Normal file
242
grub-core/kern/i386/realmode.S
Normal 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
74
grub-core/kern/i386/tsc.c
Normal 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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue