From 26798641567f3057d2a910de2a767bb810815774 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 26 Apr 2009 19:32:54 -0700 Subject: [PATCH] Remove the old mboot module --- Makefile | 4 +- com32/modules/Makefile | 3 +- com32/modules/i386-elf.h | 237 ---------- com32/modules/mb_header.h | 90 ---- com32/modules/mb_info.h | 217 --------- com32/modules/mboot.c | 1083 --------------------------------------------- 6 files changed, 3 insertions(+), 1631 deletions(-) delete mode 100644 com32/modules/i386-elf.h delete mode 100644 com32/modules/mb_header.h delete mode 100644 com32/modules/mb_info.h delete mode 100644 com32/modules/mboot.c diff --git a/Makefile b/Makefile index 5628917..bdaffe6 100644 --- a/Makefile +++ b/Makefile @@ -31,8 +31,8 @@ include $(topdir)/MCONFIG # List of module objects that should be installed for all derivatives MODULES = memdisk/memdisk memdump/memdump.com modules/*.com \ - com32/menu/*.c32 com32/modules/*.c32 com32/hdt/*.c32 \ - com32/rosh/*.c32 + com32/menu/*.c32 com32/modules/*.c32 com32/mboot/*.c32 \ + com32/hdt/*.c32 com32/rosh/*.c32 # syslinux.exe is BTARGET so as to not require everyone to have the # mingw suite installed diff --git a/com32/modules/Makefile b/com32/modules/Makefile index ba76268..e3155bd 100644 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@ -18,8 +18,7 @@ topdir = ../.. include ../MCONFIG -MODULES = chain.c32 config.c32 ethersel.c32 mboot.c32 dmitest.c32 \ - cpuidtest.c32 \ +MODULES = chain.c32 config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \ pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 meminfo.c32 \ sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 kbdmap.c32 cmd.c32 \ vpdtest.c32 diff --git a/com32/modules/i386-elf.h b/com32/modules/i386-elf.h deleted file mode 100644 index 04ddf39..0000000 --- a/com32/modules/i386-elf.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2001,2002 Free Software Foundation, Inc. - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* 32-bit data types */ - -typedef unsigned long Elf32_Addr; -typedef unsigned short Elf32_Half; -typedef unsigned long Elf32_Off; -typedef signed long Elf32_Sword; -typedef unsigned long Elf32_Word; -/* "unsigned char" already exists */ - -/* ELF header */ -typedef struct -{ - -#define EI_NIDENT 16 - - /* first four characters are defined below */ -#define EI_MAG0 0 -#define ELFMAG0 0x7f -#define EI_MAG1 1 -#define ELFMAG1 'E' -#define EI_MAG2 2 -#define ELFMAG2 'L' -#define EI_MAG3 3 -#define ELFMAG3 'F' - -#define EI_CLASS 4 /* data sizes */ -#define ELFCLASS32 1 /* i386 -- up to 32-bit data sizes present */ - -#define EI_DATA 5 /* data type and ordering */ -#define ELFDATA2LSB 1 /* i386 -- LSB 2's complement */ - -#define EI_VERSION 6 /* version number. "e_version" must be the same */ -#define EV_CURRENT 1 /* current version number */ - -#define EI_OSABI 7 /* operating system/ABI indication */ -#define ELFOSABI_FREEBSD 9 - -#define EI_ABIVERSION 8 /* ABI version */ - -#define EI_PAD 9 /* from here in is just padding */ - -#define EI_BRAND 8 /* start of OS branding (This is - obviously illegal against the ELF - standard.) */ - - unsigned char e_ident[EI_NIDENT]; /* basic identification block */ - -#define ET_EXEC 2 /* we only care about executable types */ - Elf32_Half e_type; /* file types */ - -#define EM_386 3 /* i386 -- obviously use this one */ - Elf32_Half e_machine; /* machine types */ - Elf32_Word e_version; /* use same as "EI_VERSION" above */ - Elf32_Addr e_entry; /* entry point of the program */ - Elf32_Off e_phoff; /* program header table file offset */ - Elf32_Off e_shoff; /* section header table file offset */ - Elf32_Word e_flags; /* flags */ - Elf32_Half e_ehsize; /* elf header size in bytes */ - Elf32_Half e_phentsize; /* program header entry size */ - Elf32_Half e_phnum; /* number of entries in program header */ - Elf32_Half e_shentsize; /* section header entry size */ - Elf32_Half e_shnum; /* number of entries in section header */ - -#define SHN_UNDEF 0 -#define SHN_LORESERVE 0xff00 -#define SHN_LOPROC 0xff00 -#define SHN_HIPROC 0xff1f -#define SHN_ABS 0xfff1 -#define SHN_COMMON 0xfff2 -#define SHN_HIRESERVE 0xffff - Elf32_Half e_shstrndx; /* section header table index */ -} -Elf32_Ehdr; - - -#define BOOTABLE_I386_ELF(h) \ - ((h.e_ident[EI_MAG0] == ELFMAG0) & (h.e_ident[EI_MAG1] == ELFMAG1) \ - & (h.e_ident[EI_MAG2] == ELFMAG2) & (h.e_ident[EI_MAG3] == ELFMAG3) \ - & (h.e_ident[EI_CLASS] == ELFCLASS32) & (h.e_ident[EI_DATA] == ELFDATA2LSB) \ - & (h.e_ident[EI_VERSION] == EV_CURRENT) & (h.e_type == ET_EXEC) \ - & (h.e_machine == EM_386) & (h.e_version == EV_CURRENT)) - -/* section table - ? */ -typedef struct -{ - Elf32_Word sh_name; /* Section name (string tbl index) */ - Elf32_Word sh_type; /* Section type */ - Elf32_Word sh_flags; /* Section flags */ - Elf32_Addr sh_addr; /* Section virtual addr at execution */ - Elf32_Off sh_offset; /* Section file offset */ - Elf32_Word sh_size; /* Section size in bytes */ - Elf32_Word sh_link; /* Link to another section */ - Elf32_Word sh_info; /* Additional section information */ - Elf32_Word sh_addralign; /* Section alignment */ - Elf32_Word sh_entsize; /* Entry size if section holds table */ -} -Elf32_Shdr; - -/* symbol table - page 4-25, figure 4-15 */ -typedef struct -{ - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; - unsigned char st_info; - unsigned char st_other; - Elf32_Half st_shndx; -} -Elf32_Sym; - -/* symbol type and binding attributes - page 4-26 */ - -#define ELF32_ST_BIND(i) ((i) >> 4) -#define ELF32_ST_TYPE(i) ((i) & 0xf) -#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) - -/* symbol binding - page 4-26, figure 4-16 */ - -#define STB_LOCAL 0 -#define STB_GLOBAL 1 -#define STB_WEAK 2 -#define STB_LOPROC 13 -#define STB_HIPROC 15 - -/* symbol types - page 4-28, figure 4-17 */ - -#define STT_NOTYPE 0 -#define STT_OBJECT 1 -#define STT_FUNC 2 -#define STT_SECTION 3 -#define STT_FILE 4 -#define STT_LOPROC 13 -#define STT_HIPROC 15 - - -/* Macros to split/combine relocation type and symbol page 4-32 */ - -#define ELF32_R_SYM(__i) ((__i)>>8) -#define ELF32_R_TYPE(__i) ((unsigned char) (__i)) -#define ELF32_R_INFO(__s, __t) (((__s)<<8) + (unsigned char) (__t)) - - -/* program header - page 5-2, figure 5-1 */ - -typedef struct -{ - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; -} -Elf32_Phdr; - -/* segment types - page 5-3, figure 5-2 */ - -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 - -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff - -/* segment permissions - page 5-6 */ - -#define PF_X 0x1 -#define PF_W 0x2 -#define PF_R 0x4 -#define PF_MASKPROC 0xf0000000 - - -/* dynamic structure - page 5-15, figure 5-9 */ - -typedef struct -{ - Elf32_Sword d_tag; - union - { - Elf32_Word d_val; - Elf32_Addr d_ptr; - } - d_un; -} -Elf32_Dyn; - -/* Dynamic array tags - page 5-16, figure 5-10. */ - -#define DT_NULL 0 -#define DT_NEEDED 1 -#define DT_PLTRELSZ 2 -#define DT_PLTGOT 3 -#define DT_HASH 4 -#define DT_STRTAB 5 -#define DT_SYMTAB 6 -#define DT_RELA 7 -#define DT_RELASZ 8 -#define DT_RELAENT 9 -#define DT_STRSZ 10 -#define DT_SYMENT 11 -#define DT_INIT 12 -#define DT_FINI 13 -#define DT_SONAME 14 -#define DT_RPATH 15 -#define DT_SYMBOLIC 16 -#define DT_REL 17 -#define DT_RELSZ 18 -#define DT_RELENT 19 -#define DT_PLTREL 20 -#define DT_DEBUG 21 -#define DT_TEXTREL 22 -#define DT_JMPREL 23 diff --git a/com32/modules/mb_header.h b/com32/modules/mb_header.h deleted file mode 100644 index 4215323..0000000 --- a/com32/modules/mb_header.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000 Free Software Foundation, Inc. - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * MultiBoot Header description - */ - -struct multiboot_header -{ - /* Must be MULTIBOOT_MAGIC - see below. */ - unsigned magic; - - /* Feature flags - see below. */ - unsigned flags; - - /* - * Checksum - * - * The above fields plus this one must equal 0 mod 2^32. - */ - unsigned checksum; - - /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ - unsigned header_addr; - unsigned load_addr; - unsigned load_end_addr; - unsigned bss_end_addr; - unsigned entry_addr; - - /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ - unsigned mode_type; - unsigned width; - unsigned height; - unsigned depth; -}; - -/* - * The entire multiboot_header must be contained - * within the first MULTIBOOT_SEARCH bytes of the kernel image. - */ -#define MULTIBOOT_SEARCH 8192 -#define MULTIBOOT_FOUND(addr, len) \ - (! ((addr) & 0x3) \ - && (len) >= 12 \ - && *((int *) (addr)) == MULTIBOOT_MAGIC \ - && ! (*((unsigned *) (addr)) + *((unsigned *) (addr + 4)) \ - + *((unsigned *) (addr + 8))) \ - && (! (MULTIBOOT_AOUT_KLUDGE & *((int *) (addr + 4))) || (len) >= 32) \ - && (! (MULTIBOOT_VIDEO_MODE & *((int *) (addr + 4))) || (len) >= 48)) - -/* Magic value identifying the multiboot_header. */ -#define MULTIBOOT_MAGIC 0x1BADB002 - -/* - * Features flags for 'flags'. - * If a boot loader sees a flag in MULTIBOOT_MUSTKNOW set - * and it doesn't understand it, it must fail. - */ -#define MULTIBOOT_MUSTKNOW 0x0000FFFF - -/* currently unsupported flags... this is a kind of version number. */ -#define MULTIBOOT_UNSUPPORTED 0x0000FFF8 - -/* Align all boot modules on i386 page (4KB) boundaries. */ -#define MULTIBOOT_PAGE_ALIGN 0x00000001 - -/* Must pass memory information to OS. */ -#define MULTIBOOT_MEMORY_INFO 0x00000002 - -/* Must pass video information to OS. */ -#define MULTIBOOT_VIDEO_MODE 0x00000004 - -/* This flag indicates the use of the address fields in the header. */ -#define MULTIBOOT_AOUT_KLUDGE 0x00010000 diff --git a/com32/modules/mb_info.h b/com32/modules/mb_info.h deleted file mode 100644 index 91a1392..0000000 --- a/com32/modules/mb_info.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000 Free Software Foundation, Inc. - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * The structure type "mod_list" is used by the "multiboot_info" structure. - */ - -struct mod_list -{ - /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ - unsigned long mod_start; - unsigned long mod_end; - - /* Module command line */ - unsigned long cmdline; - - /* padding to take it to 16 bytes (must be zero) */ - unsigned long pad; -}; - - -/* - * INT-15, AX=E820 style "AddressRangeDescriptor" - * ...with a "size" parameter on the front which is the structure size - 4, - * pointing to the next one, up until the full buffer length of the memory - * map has been reached. - */ - -struct AddrRangeDesc -{ - unsigned long size; - unsigned long long BaseAddr; - unsigned long long Length; - unsigned long Type; - - /* unspecified optional padding... */ -}; - -/* usable memory "Type", all others are reserved. */ -#define MB_ARD_MEMORY 1 - - -/* Drive Info structure. */ -struct drive_info -{ - /* The size of this structure. */ - unsigned long size; - - /* The BIOS drive number. */ - unsigned char drive_number; - - /* The access mode (see below). */ - unsigned char drive_mode; - - /* The BIOS geometry. */ - unsigned short drive_cylinders; - unsigned char drive_heads; - unsigned char drive_sectors; - - /* The array of I/O ports used for the drive. */ - unsigned short drive_ports[0]; -}; - -/* Drive Mode. */ -#define MB_DI_CHS_MODE 0 -#define MB_DI_LBA_MODE 1 - - -/* APM BIOS info. */ -struct apm_info -{ - unsigned short version; - unsigned short cseg; - unsigned long offset; - unsigned short cseg_16; - unsigned short dseg_16; - unsigned short cseg_len; - unsigned short cseg_16_len; - unsigned short dseg_16_len; -}; - - -/* - * MultiBoot Info description - * - * This is the struct passed to the boot image. This is done by placing - * its address in the EAX register. - */ - -struct multiboot_info -{ - /* MultiBoot info version number */ - unsigned long flags; - - /* Available memory from BIOS */ - unsigned long mem_lower; - unsigned long mem_upper; - - /* "root" partition */ - unsigned long boot_device; - - /* Kernel command line */ - unsigned long cmdline; - - /* Boot-Module list */ - unsigned long mods_count; - unsigned long mods_addr; - - union - { - struct - { - /* (a.out) Kernel symbol table info */ - unsigned long tabsize; - unsigned long strsize; - unsigned long addr; - unsigned long pad; - } - a; - - struct - { - /* (ELF) Kernel section header table */ - unsigned long num; - unsigned long size; - unsigned long addr; - unsigned long shndx; - } - e; - } - syms; - - /* Memory Mapping buffer */ - unsigned long mmap_length; - unsigned long mmap_addr; - - /* Drive Info buffer */ - unsigned long drives_length; - unsigned long drives_addr; - - /* ROM configuration table */ - unsigned long config_table; - - /* Boot Loader Name */ - unsigned long boot_loader_name; - - /* APM table */ - unsigned long apm_table; - - /* Video */ - unsigned long vbe_control_info; - unsigned long vbe_mode_info; - unsigned short vbe_mode; - unsigned short vbe_interface_seg; - unsigned short vbe_interface_off; - unsigned short vbe_interface_len; -}; - -/* - * Flags to be set in the 'flags' parameter above - */ - -/* is there basic lower/upper memory information? */ -#define MB_INFO_MEMORY 0x00000001 -/* is there a boot device set? */ -#define MB_INFO_BOOTDEV 0x00000002 -/* is the command-line defined? */ -#define MB_INFO_CMDLINE 0x00000004 -/* are there modules to do something with? */ -#define MB_INFO_MODS 0x00000008 - -/* These next two are mutually exclusive */ - -/* is there a symbol table loaded? */ -#define MB_INFO_AOUT_SYMS 0x00000010 -/* is there an ELF section header table? */ -#define MB_INFO_ELF_SHDR 0x00000020 - -/* is there a full memory map? */ -#define MB_INFO_MEM_MAP 0x00000040 - -/* Is there drive info? */ -#define MB_INFO_DRIVE_INFO 0x00000080 - -/* Is there a config table? */ -#define MB_INFO_CONFIG_TABLE 0x00000100 - -/* Is there a boot loader name? */ -#define MB_INFO_BOOT_LOADER_NAME 0x00000200 - -/* Is there a APM table? */ -#define MB_INFO_APM_TABLE 0x00000400 - -/* Is there video information? */ -#define MB_INFO_VIDEO_INFO 0x00000800 - -/* - * The following value must be present in the EAX register. - */ - -#define MULTIBOOT_VALID 0x2BADB002 diff --git a/com32/modules/mboot.c b/com32/modules/mboot.c deleted file mode 100644 index edcb88e..0000000 --- a/com32/modules/mboot.c +++ /dev/null @@ -1,1083 +0,0 @@ -/* - * mboot.c - * - * Loader for Multiboot-compliant kernels and modules. - * - * Copyright (C) 2005 Tim Deegan - * Parts based on GNU GRUB, Copyright 2000 Free Software Foundation, Inc. - * Parts based on SYSLINUX, Copyright 1994-2008 H. Peter Anvin. - * Thanks to Ram Yalamanchili for the ELF section-header loading. - * - * This program 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 2 of the - * License, or (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "i386-elf.h" -#include "mb_info.h" -#include "mb_header.h" - -#include /* For __constructor */ - -#define MIN(_x, _y) (((_x)<(_y))?(_x):(_y)) -#define MAX(_x, _y) (((_x)>(_y))?(_x):(_y)) - -/* Define this for some more printout */ -#undef DEBUG - -/* Memory magic numbers */ -#define STACK_SIZE 0x20000 /* XXX Could be much smaller */ -#define MALLOC_SIZE 0x100000 /* XXX Could be much smaller */ -#define MIN_RUN_ADDR 0x10000 /* Lowest address we'll consider using */ -#define MEM_HOLE_START 0xa0000 /* Memory hole runs from 640k ... */ -#define MEM_HOLE_END 0x100000 /* ... to 1MB */ -#define X86_PAGE_SIZE 0x1000 -#define DHCP_ACK_SIZE 2048 /* Maximum size of the DHCP ACK package. - Probably too large since we're interested - in the first bunch of bytes only. */ - -size_t __stack_size = STACK_SIZE; /* How much stack we'll use */ -extern void *__mem_end; /* Start of malloc() heap */ -extern char _end[]; /* End of static data */ - -/* Pointer to free memory for loading into: load area is between here - * and section_addr */ -static char *next_load_addr; - -/* Memory map for run-time */ -typedef struct section section_t; -struct section { - size_t dest; /* Start of run-time allocation */ - char *src; /* Current location of data for memmove(), - * or NULL for bzero() */ - size_t size; /* Length of allocation */ -}; -static char *section_addr; -static int section_count; - -static size_t max_run_addr; /* Highest address we'll consider using */ -static size_t next_mod_run_addr; /* Where the next module will be put */ - -/* File loads are in units of this much */ -#define LOAD_CHUNK 0x20000 - -/* Layout of the input to the 32-bit lidt instruction */ -struct lidt_operand { - unsigned int limit:16; - unsigned int base:32; -} __attribute__((packed)); - -/* Magic strings */ -static const char version_string[] = "COM32 Multiboot loader v0.2"; -static const char copyright_string[] = "Copyright (C) 2005-2006 Tim Deegan."; -static const char module_separator[] = "---"; - - -/* - * Start of day magic, run from __start during library init. - */ - -static void __constructor check_version(void) - /* Check the SYSLINUX version. Docs say we should be OK from v2.08, - * but in fact we crash on anything below v2.12 (when libc came in). */ -{ - com32sys_t regs_in, regs_out; - const char *p, *too_old = "Fatal: SYSLINUX image is too old; " - "mboot.c32 needs at least version 2.12.\r\n"; - - memset(®s_in, 0, sizeof(regs_in)); - regs_in.eax.l = 0x0001; /* "Get version" */ - __intcall(0x22, ®s_in, ®s_out); - if (regs_out.ecx.w[0] >= 0x020c) return; - - /* Pointless: on older versions this print fails too. :( */ - for (p = too_old ; *p ; p++) { - memset(®s_in, 0, sizeof(regs_in)); - regs_in.eax.b[1] = 0x02; /* "Write character" */ - regs_in.edx.b[0] = *p; - __intcall(0x21, ®s_in, ®s_out); - } - - __intcall(0x20, ®s_in, ®s_out); /* "Terminate program" */ -} - - -static void __constructor grab_memory(void) - /* Runs before init_memory_arena() (com32/lib/malloc.c) to let - * the malloc() code know how much space it's allowed to use. - * We don't use malloc() directly, but some of the library code - * does (zlib, for example). */ -{ - /* Find the stack pointer */ - register char * sp; - asm volatile("movl %%esp, %0" : "=r" (sp)); - - /* Initialize the allocation of *run-time* memory: don't let ourselves - * overwrite the stack during the relocation later. */ - max_run_addr = (size_t) sp - (MALLOC_SIZE + STACK_SIZE); - - /* Move the end-of-memory marker: malloc() will use only memory - * above __mem_end and below the stack. We will load files starting - * at the old __mem_end and working towards the new one, and allocate - * section descriptors at the top of that area, working down. */ - next_load_addr = __mem_end; - section_addr = sp - (MALLOC_SIZE + STACK_SIZE); - section_count = 0; - - /* But be careful not to move it the wrong direction if memory is - * tight. Instead we'll fail more gracefully later, when we try to - * load a file and find that next_load_addr > section_addr. */ - __mem_end = MAX(section_addr, next_load_addr); -} - - - - -/* - * Run-time memory map functions: allocating and recording allocations. - */ - -static int cmp_sections(const void *a, const void *b) - /* For sorting section descriptors by destination address */ -{ - const section_t *sa = a; - const section_t *sb = b; - if (sa->dest < sb->dest) return -1; - if (sa->dest > sb->dest) return 1; - return 0; -} - - -static void add_section(size_t dest, char *src, size_t size) - /* Adds something to the list of sections to relocate. */ -{ - section_t *sec; - -#ifdef DEBUG - printf("SECTION: %#8.8x --> %#8.8x (%#x)\n", (size_t) src, dest, size); -#endif - - section_addr -= sizeof (section_t); - if (section_addr < next_load_addr) { - printf("Fatal: out of memory allocating section descriptor.\n"); - exit(1); - } - sec = (section_t *) section_addr; - section_count++; - - sec->src = src; - sec->dest = dest; - sec->size = size; - - /* Keep the list sorted */ - qsort(sec, section_count, sizeof (section_t), cmp_sections); -} - - -static size_t place_low_section(size_t size, size_t align) - /* Find a space in the run-time memory map, below 640K */ -{ - int i; - size_t start; - section_t *sections = (section_t *) section_addr; - - start = MIN_RUN_ADDR; - start = (start + (align-1)) & ~(align-1); - - /* Section list is sorted by destination, so can do this in one pass */ - for (i = 0; i < section_count; i++) { - if (sections[i].dest < start + size) { - /* Hit the bottom of this section */ - start = sections[i].dest + sections[i].size; - start = (start + (align-1)) & ~(align-1); - } - } - if (start + size < MEM_HOLE_START) return start; - else return 0; -} - - -static size_t place_module_section(size_t size, size_t align) - /* Find a space in the run-time memory map for this module. */ -{ - /* Ideally we'd run through the sections looking for a free space - * like place_low_section() does, but some OSes (Xen, at least) - * assume that the bootloader has loaded all the modules - * consecutively, above the kernel. So, what we actually do is - * keep a pointer to the highest address allocated so far, and - * always allocate modules there. */ - - size_t start = next_mod_run_addr; - start = (start + (align-1)) & ~(align-1); - - if (start + size > max_run_addr) return 0; - - next_mod_run_addr = start + size; - return start; -} - - -static void place_kernel_section(size_t start, size_t size) - /* Allocate run-time space for part of the kernel, checking for - * sanity. We assume the kernel isn't broken enough to have - * overlapping segments. */ -{ - /* We always place modules above the kernel */ - next_mod_run_addr = MAX(next_mod_run_addr, start + size); - - if (start > max_run_addr || start + size > max_run_addr) { - /* Overruns the end of memory */ - printf("Fatal: kernel loads too high (%#8.8x+%#x > %#8.8x).\n", - start, size, max_run_addr); - exit(1); - } - if (start >= MEM_HOLE_END) { - /* Above the memory hole: easy */ -#ifdef DEBUG - printf("Placed kernel section (%#8.8x+%#x)\n", start, size); -#endif - return; - } - if (start >= MEM_HOLE_START) { - /* In the memory hole. Not so good */ - printf("Fatal: kernel load address (%#8.8x) is in the memory hole.\n", - start); - exit(1); - } - if (start + size > MEM_HOLE_START) { - /* Too big for low memory */ - printf("Fatal: kernel (%#8.8x+%#x) runs into the memory hole.\n", - start, size); - exit(1); - } - if (start < MIN_RUN_ADDR) { - /* Loads too low */ - printf("Fatal: kernel load address (%#8.8x) is too low (<%#8.8x).\n", - start, MIN_RUN_ADDR); - exit(1); - } - /* Kernel loads below the memory hole: OK */ -#ifdef DEBUG - printf("Placed kernel section (%#8.8x+%#x)\n", start, size); -#endif -} - - -static void reorder_sections(void) - /* Reorders sections into a safe order, where no relocation - * overwrites the source of a later one. */ -{ - section_t *secs = (section_t *) section_addr; - section_t tmp; - int i, j, tries; - -#ifdef DEBUG - printf("Relocations:\n"); - for (i = 0; i < section_count ; i++) { - printf(" %#8.8x --> %#8.8x (%#x)\n", - (size_t)secs[i].src, secs[i].dest, secs[i].size); - } -#endif - - for (i = 0; i < section_count; i++) { - tries = 0; - scan_again: - for (j = i + 1 ; j < section_count; j++) { - if (secs[j].src != NULL - && secs[i].dest + secs[i].size > (size_t) secs[j].src - && secs[i].dest < (size_t) secs[j].src + secs[j].size) { - /* Would overwrite the source of the later move */ - if (++tries > section_count) { - /* Deadlock! */ - /* XXX Try to break deadlocks? */ - printf("Fatal: circular dependence in relocations.\n"); - exit(1); - } - /* Swap these sections (using struct copies) */ - tmp = secs[i]; secs[i] = secs[j]; secs[j] = tmp; - /* Start scanning again from the new secs[i]... */ - goto scan_again; - } - } - } - -#ifdef DEBUG - printf("Relocations:\n"); - for (i = 0; i < section_count ; i++) { - printf(" %#8.8x --> %#8.8x (%#x)\n", - (size_t)secs[i].src, secs[i].dest, secs[i].size); - } -#endif -} - - -static void init_mmap(struct multiboot_info *mbi) - /* Get a full memory map from the BIOS to pass to the kernel. */ -{ - com32sys_t regs_in, regs_out; - struct AddrRangeDesc *e820; - int e820_slots; - size_t mem_lower, mem_upper, run_addr, mmap_size; - register size_t sp; - - /* Default values for mem_lower and mem_upper in case the BIOS won't - * tell us: 640K, and all memory up to the stack. */ - asm volatile("movl %%esp, %0" : "=r" (sp)); - mem_upper = (sp - MEM_HOLE_END) / 1024; - mem_lower = (MEM_HOLE_START) / 1024; - -#ifdef DEBUG - printf("Requesting memory map from BIOS:\n"); -#endif - - /* Ask the BIOS for the full memory map of the machine. We'll - * build it in Multiboot format (i.e. with size fields) in the - * bounce buffer, and then allocate some high memory to keep it in - * until boot time. */ - e820 = __com32.cs_bounce; - e820_slots = 0; - regs_out.ebx.l = 0; - - while(((void *)(e820 + 1)) < __com32.cs_bounce + __com32.cs_bounce_size) - { - memset(e820, 0, sizeof (*e820)); - memset(®s_in, 0, sizeof regs_in); - e820->size = sizeof(*e820) - sizeof(e820->size); - - /* Ask the BIOS to fill in this descriptor */ - regs_in.eax.l = 0xe820; /* "Get system memory map" */ - regs_in.ebx.l = regs_out.ebx.l; /* Continuation value from last call */ - regs_in.ecx.l = 20; /* Size of buffer to write into */ - regs_in.edx.l = 0x534d4150; /* "SMAP" */ - regs_in.es = SEG(&e820->BaseAddr); - regs_in.edi.w[0] = OFFS(&e820->BaseAddr); - __intcall(0x15, ®s_in, ®s_out); - - if ((regs_out.eflags.l & EFLAGS_CF) != 0 && regs_out.ebx.l != 0) - break; /* End of map */ - - if (((regs_out.eflags.l & EFLAGS_CF) != 0 && regs_out.ebx.l == 0) - || (regs_out.eax.l != 0x534d4150)) - { - /* Error */ - printf("Error %x reading E820 memory map: %s.\n", - (int) regs_out.eax.b[0], - (regs_out.eax.b[0] == 0x80) ? "invalid command" : - (regs_out.eax.b[0] == 0x86) ? "not supported" : - "unknown error"); - break; - } - - /* Success */ -#ifdef DEBUG - printf(" %#16.16Lx -- %#16.16Lx : ", - e820->BaseAddr, e820->BaseAddr + e820->Length); - switch (e820->Type) { - case 1: printf("Available\n"); break; - case 2: printf("Reserved\n"); break; - case 3: printf("ACPI Reclaim\n"); break; - case 4: printf("ACPI NVS\n"); break; - default: printf("? (Reserved)\n"); break; - } -#endif - - if (e820->Type == 1) { - if (e820->BaseAddr == 0) { - mem_lower = MIN(MEM_HOLE_START, e820->Length) / 1024; - } else if (e820->BaseAddr == MEM_HOLE_END) { - mem_upper = MIN(0xfff00000, e820->Length) / 1024; - } - } - - /* Move to next slot */ - e820++; - e820_slots++; - - /* Done? */ - if (regs_out.ebx.l == 0) - break; - } - - /* Record the simple information in the MBI */ - mbi->flags |= MB_INFO_MEMORY; - mbi->mem_lower = mem_lower; - mbi->mem_upper = mem_upper; - - /* Record the full memory map in the MBI */ - if (e820_slots != 0) { - mmap_size = e820_slots * sizeof(*e820); - /* Where will it live at run time? */ - run_addr = place_low_section(mmap_size, 1); - if (run_addr == 0) { - printf("Fatal: can't find space for the e820 mmap.\n"); - exit(1); - } - /* Where will it live now? */ - e820 = (struct AddrRangeDesc *) next_load_addr; - if (next_load_addr + mmap_size > section_addr) { - printf("Fatal: out of memory storing the e820 mmap.\n"); - exit(1); - } - next_load_addr += mmap_size; - /* Copy it out of the bounce buffer */ - memcpy(e820, __com32.cs_bounce, mmap_size); - /* Remember to copy it again at run time */ - add_section(run_addr, (char *) e820, mmap_size); - /* Record it in the MBI */ - mbi->flags |= MB_INFO_MEM_MAP; - mbi->mmap_length = mmap_size; - mbi->mmap_addr = run_addr; - } -} - - - - -/* - * Code for loading and parsing files. - */ - -static void load_file(char *filename, char **startp, size_t *sizep) - /* Load a file into memory. Returns where it is and how big via - * startp and sizep */ -{ - gzFile fp; - char *start; - int bsize; - - printf("Loading %s.", filename); - - start = next_load_addr; - startp[0] = start; - sizep[0] = 0; - - /* Open the file */ - if ((fp = gzopen(filename, "r")) == NULL) { - printf("\nFatal: cannot open %s\n", filename); - exit(1); - } - - while (next_load_addr + LOAD_CHUNK <= section_addr) { - bsize = gzread(fp, next_load_addr, LOAD_CHUNK); - printf("%s","."); - - if (bsize < 0) { - printf("\nFatal: read error in %s\n", filename); - gzclose(fp); - exit(1); - } - - next_load_addr += bsize; - sizep[0] += bsize; - - if (bsize < LOAD_CHUNK) { - printf("%s","\n"); - gzclose(fp); - return; - } - } - - /* Running out of memory. Try and use up the last bit */ - if (section_addr > next_load_addr) { - bsize = gzread(fp, next_load_addr, section_addr - next_load_addr); - printf("%s","."); - } else { - bsize = 0; - } - - if (bsize < 0) { - gzclose(fp); - printf("\nFatal: read error in %s\n", filename); - exit(1); - } - - next_load_addr += bsize; - sizep[0] += bsize; - - if (!gzeof(fp)) { - gzclose(fp); - printf("\nFatal: out of memory reading %s\n", filename); - exit(1); - } - - printf("%s","\n"); - gzclose(fp); - return; -} - - -static size_t load_kernel(struct multiboot_info *mbi, char *cmdline) - /* Load a multiboot/elf32 kernel and allocate run-time memory for it. - * Returns the kernel's entry address. */ -{ - unsigned int i; - char *load_addr; /* Where the image was loaded */ - size_t load_size; /* How big it is */ - char *seg_addr; /* Where a segment was loaded */ - size_t seg_size, bss_size; /* How big it is */ - size_t run_addr, run_size; /* Where it should be put */ - size_t shdr_run_addr; - char *p; - Elf32_Ehdr *ehdr; - Elf32_Phdr *phdr; - Elf32_Shdr *shdr; - struct multiboot_header *mbh; - - printf("Kernel: %s\n", cmdline); - - load_addr = 0; - load_size = 0; - p = strchr(cmdline, ' '); - if (p != NULL) *p = 0; - load_file(cmdline, &load_addr, &load_size); - if (load_size < 12) { - printf("Fatal: %s is too short to be a multiboot kernel.", - cmdline); - exit(1); - } - if (p != NULL) *p = ' '; - - - /* Look for a multiboot header in the first 8k of the file */ - for (i = 0; i <= MIN(load_size - 12, MULTIBOOT_SEARCH - 12); i += 4) - { - mbh = (struct multiboot_header *)(load_addr + i); - if (mbh->magic != MULTIBOOT_MAGIC - || ((mbh->magic+mbh->flags+mbh->checksum) & 0xffffffff)) - { - /* Not a multiboot header */ - continue; - } - if (mbh->flags & (MULTIBOOT_UNSUPPORTED | MULTIBOOT_VIDEO_MODE)) { - /* Requires options we don't support */ - printf("Fatal: Kernel requires multiboot options " - "that I don't support: %#x.\n", - mbh->flags & (MULTIBOOT_UNSUPPORTED|MULTIBOOT_VIDEO_MODE)); - exit(1); - } - - /* This kernel will do: figure out where all the pieces will live */ - - /* Look for a bootable ELF32 header */ - if ((load_size > sizeof(Elf32_Ehdr) && - BOOTABLE_I386_ELF((*((Elf32_Ehdr *) load_addr))))) { - - ehdr = (Elf32_Ehdr *)load_addr; - if (ehdr->e_phoff + ehdr->e_phnum*sizeof (*phdr) > load_size) { - printf("Fatal: malformed ELF header overruns EOF.\n"); - exit(1); - } - if (ehdr->e_phnum <= 0) { - printf("Fatal: ELF kernel has no program headers.\n"); - exit(1); - } - -#ifdef DEBUG - printf("Using ELF header.\n"); -#endif - - if (ehdr->e_type != ET_EXEC - || ehdr->e_version != EV_CURRENT - || ehdr->e_phentsize != sizeof (Elf32_Phdr)) { - printf("Warning: funny-looking ELF header.\n"); - } - phdr = (Elf32_Phdr *)(load_addr + ehdr->e_phoff); - - /* Obey the program headers to load the kernel */ - for(i = 0; i < ehdr->e_phnum; i++) { - - /* How much is in this segment? */ - run_size = phdr[i].p_memsz; - if (phdr[i].p_type != PT_LOAD) - seg_size = 0; - else - seg_size = (size_t)phdr[i].p_filesz; - - /* Where is it in the loaded file? */ - seg_addr = load_addr + phdr[i].p_offset; - if (seg_addr + seg_size > load_addr + load_size) { - printf("Fatal: ELF load segment runs off the " - "end of the file.\n"); - exit(1); - } - - /* Skip segments that don't take up any memory */ - if (run_size == 0) continue; - - /* Place the segment where it wants to be */ - run_addr = phdr[i].p_paddr; - place_kernel_section(run_addr, run_size); - - /* Put it on the relocation list */ - if (seg_size < run_size) { - /* Set up the kernel BSS too */ - if (seg_size > 0) - add_section(run_addr, seg_addr, seg_size); - bss_size = run_size - seg_size; - add_section(run_addr + seg_size, NULL, bss_size); - } else { - /* No BSS */ - add_section(run_addr, seg_addr, run_size); - } - } - - if (ehdr->e_shoff != 0) { -#ifdef DEBUG - printf("Loading ELF section table.\n"); -#endif - /* Section Header */ - shdr = (Elf32_Shdr *)(load_addr + ehdr->e_shoff); - - /* Section Header Table size */ - run_size = ehdr->e_shentsize * ehdr->e_shnum; - shdr_run_addr = place_module_section(run_size, 0x1000); - if (shdr_run_addr == 0) { - printf("Warning: Not enough memory to load the " - "section table.\n"); - return ehdr->e_entry; - } - add_section(shdr_run_addr, (void*) shdr, run_size); - - /* Load section tables not loaded thru program segments */ - for (i = 0; i < ehdr->e_shnum; i++) { - /* This case is when this section is already included in - * program header or it's 0 size, so no need to load */ - if (shdr[i].sh_addr != 0 || !shdr[i].sh_size) - continue; - - if (shdr[i].sh_addralign == 0) - shdr[i].sh_addralign = 1; - - run_addr = place_module_section(shdr[i].sh_size, - shdr[i].sh_addralign); - if (run_addr == 0) { - printf("Warning: Not enough memory to load " - "section %d.\n", i); - return ehdr->e_entry; - } - shdr[i].sh_addr = run_addr; - add_section(run_addr, - (void*) (shdr[i].sh_offset + load_addr), - shdr[i].sh_size); - } - - mbi->flags |= MB_INFO_ELF_SHDR; - mbi->syms.e.num = ehdr->e_shnum; - mbi->syms.e.size = ehdr->e_shentsize; - mbi->syms.e.shndx = ehdr->e_shstrndx; - mbi->syms.e.addr = shdr_run_addr; -#ifdef DEBUG - printf("Section information: shnum: %lu, entSize: %lu, " - "shstrndx: %lu, addr: 0x%lx\n", - mbi->syms.e.num, mbi->syms.e.size, - mbi->syms.e.shndx, mbi->syms.e.addr); -#endif - } - - /* Done! */ - return ehdr->e_entry; - } else - - /* Does the MB header specify load addresses? */ - if (mbh->flags & MULTIBOOT_AOUT_KLUDGE) { - - /* Use the offsets in the multiboot header */ -#ifdef DEBUG - printf("Using multiboot header.\n"); -#endif - - /* Where is the code in the loaded file? */ - seg_addr = ((char *)mbh) - (mbh->header_addr - mbh->load_addr); - - /* How much code is there? */ - run_addr = mbh->load_addr; - if (mbh->load_end_addr != 0) - seg_size = mbh->load_end_addr - mbh->load_addr; - else - seg_size = load_size - (seg_addr - load_addr); - - /* How much memory will it take up? */ - if (mbh->bss_end_addr != 0) - run_size = mbh->bss_end_addr - mbh->load_addr; - else - run_size = seg_size; - - if (seg_size > run_size) { - printf("Fatal: can't put %i bytes of kernel into %i bytes " - "of memory.\n", seg_size, run_size); - exit(1); - } - if (seg_addr + seg_size > load_addr + load_size) { - printf("Fatal: multiboot load segment runs off the " - "end of the file.\n"); - exit(1); - } - - /* Does it fit where it wants to be? */ - place_kernel_section(run_addr, run_size); - - /* Put it on the relocation list */ - if (seg_size < run_size) { - /* Set up the kernel BSS too */ - if (seg_size > 0) - add_section(run_addr, seg_addr, seg_size); - bss_size = run_size - seg_size; - add_section(run_addr + seg_size, NULL, bss_size); - } else { - /* No BSS */ - add_section(run_addr, seg_addr, run_size); - } - - /* Done. */ - return mbh->entry_addr; - } - } - - /* This is not a multiboot kernel */ - printf("Fatal: not a multiboot kernel.\n"); - exit(1); -} - - - -static void load_module(struct mod_list *mod, char *cmdline) - /* Load a multiboot module and allocate a memory area for it */ -{ - char *load_addr, *p; - size_t load_size, run_addr; - - printf("Module: %s\n", cmdline); - - load_addr = 0; - load_size = 0; - p = strchr(cmdline, ' '); - if (p != NULL) *p = 0; - load_file(cmdline, &load_addr, &load_size); - if (p != NULL) *p = ' '; - - /* Decide where it's going to live */ - run_addr = place_module_section(load_size, X86_PAGE_SIZE); - if (run_addr == 0) { - printf("Fatal: can't find space for this module.\n"); - exit(1); - } - add_section(run_addr, load_addr, load_size); - - /* Remember where we put it */ - mod->mod_start = run_addr; - mod->mod_end = run_addr + load_size; - mod->pad = 0; - -#ifdef DEBUG - printf("Placed module (%#8.8x+%#x)\n", run_addr, load_size); -#endif -} - - - - -/* - * Code for shuffling sections into place and booting the new kernel - */ - -static void trampoline_start(section_t *secs, int sec_count, - size_t mbi_run_addr, size_t entry) - /* Final shuffle-and-boot code. Running on the stack; no external code - * or data can be relied on. */ -{ - int i; - struct lidt_operand idt; - - /* SYSLINUX has set up SS, DS and ES as 32-bit 0--4G data segments, - * but doesn't specify FS and GS. Multiboot wants them all to be - * the same, so we'd better do that before we overwrite the GDT. */ - asm volatile("movl %ds, %ecx; movl %ecx, %fs; movl %ecx, %gs"); - - /* Turn off interrupts */ - asm volatile("cli"); - - /* SYSLINUX has set up an IDT at 0x100000 that does all the - * comboot calls, and we're about to overwrite it. The Multiboot - * spec says that the kernel must set up its own IDT before turning - * on interrupts, but it's still entitled to use BIOS calls, so we'll - * put the IDT back to the BIOS one at the base of memory. */ - idt.base = 0; - idt.limit = 0x800; - asm volatile("lidt %0" : : "m" (idt)); - - /* Now, shuffle the sections */ - for (i = 0; i < sec_count; i++) { - if (secs[i].src == NULL) { - /* asm bzero() code from com32/lib/memset.c */ - char *q = (char *) secs[i].dest; - size_t nl = secs[i].size >> 2; - asm volatile("rep ; stosl ; movl %3,%0 ; rep ; stosb" - : "+c" (nl), "+D" (q) - : "a" (0x0U), "r" (secs[i].size & 3)); - } else { - /* asm memmove() code from com32/lib/memmove.c */ - const char *p = secs[i].src; - char *q = (char *) secs[i].dest; - size_t n = secs[i].size; - if ( q < p ) { - asm volatile("rep ; movsb" - : "+c" (n), "+S" (p), "+D" (q)); - } else { - p += (n-1); - q += (n-1); - asm volatile("std ; rep ; movsb ; cld" - : "+c" (n), "+S" (p), "+D" (q)); - } - } - } - - /* Now set up the last tiny bit of Multiboot environment. - * A20 is already enabled. - * CR0 already has PG cleared and PE set. - * EFLAGS already has VM and IF cleared. - * ESP is the kernels' problem. - * GDTR is the kernel's problem. - * CS is already a 32-bit, 0--4G code segments. - * DS, ES, FS and GS are already 32-bit, 0--4G data segments. - * - * EAX must be 0x2badb002 and EBX must point to the MBI when we jump. */ - - asm volatile ("jmp %*%2" - : : "a" (0x2badb002), "b" (mbi_run_addr), "cdSDm" (entry)); -} -static void trampoline_end(void) {} - - -static void boot(size_t mbi_run_addr, size_t entry) - /* Tidy up SYSLINUX, shuffle memory and boot the kernel */ -{ - com32sys_t regs; - section_t *tr_sections; - void (*trampoline)(section_t *, int, size_t, size_t); - size_t trampoline_size; - - /* Make sure the relocations are safe. */ - reorder_sections(); - - /* Copy the shuffle-and-boot code and the array of relocations - * onto the memory we previously used for malloc() heap. This is - * safe because it's not the source or the destination of any - * copies, and there'll be no more library calls after the copy. */ - - tr_sections = ((section_t *) section_addr) + section_count; - trampoline = (void *) (tr_sections + section_count); - trampoline_size = (void *)&trampoline_end - (void *)&trampoline_start; - -#ifdef DEBUG - printf("tr_sections: %p\n" - "trampoline: %p\n" - "trampoline_size: %#8.8x\n" - "max_run_addr: %#8.8x\n", - tr_sections, trampoline, trampoline_size, max_run_addr); -#endif - - printf("Booting: MBI=%#8.8x, entry=%#8.8x\n", mbi_run_addr, entry); - - memmove(tr_sections, section_addr, section_count * sizeof (section_t)); - memmove(trampoline, trampoline_start, trampoline_size); - - /* Tell SYSLINUX to clean up */ - memset(®s, 0, sizeof regs); - regs.eax.l = 0x000c; /* "Perform final cleanup" */ - regs.edx.l = 0; /* "Normal cleanup" */ - __intcall(0x22, ®s, NULL); - - /* Into the unknown */ - trampoline(tr_sections, section_count, mbi_run_addr, entry); -} - - -int main(int argc, char **argv) - /* Parse the command-line and invoke loaders */ -{ - struct multiboot_info *mbi; - struct mod_list *modp; - int modules, num_append_args; - int mbi_reloc_offset; - char *p; - size_t mbi_run_addr, mbi_size, entry; - int i; - bool opt_solaris = false; - void *dhcpdata; - size_t dhcplen; - - /* Say hello */ - openconsole(&dev_null_r, &dev_stdcon_w); - - printf("%s. %s\n", version_string, copyright_string); - - /* This is way too ugly. */ - if (!strcmp("-solaris", argv[1])) { - opt_solaris = true; - argv[1] = argv[0]; - argv = &argv[1]; - argc -= 1; - } - - if (argc < 2 || !strcmp(argv[1], module_separator)) { - printf("Fatal: No kernel filename!\n"); - exit(1); - } - -#ifdef DEBUG - printf("_end: %p\n" - "argv[1]: %p\n" - "next_load_addr: %p\n" - "section_addr %p\n" - "__mem_end: %p\n" - "argv[0]: %p\n", - &_end, argv[1], next_load_addr, section_addr, __mem_end, argv[0]); -#endif - - /* How much space will the MBI need? */ - modules = 0; - mbi_size = sizeof(struct multiboot_info) + strlen(version_string) + 5; - for (i = 1 ; i < argc ; i++) { - if (!strcmp(argv[i], module_separator)) { - modules++; - mbi_size += sizeof(struct mod_list) + 1; - } else { - mbi_size += strlen(argv[i]) + 1; - } - } - if (opt_solaris) - mbi_size += DHCP_ACK_SIZE; - - /* Allocate space in the load buffer for the MBI, all the command - * lines, and all the module details. */ - mbi = (struct multiboot_info *)next_load_addr; - next_load_addr += mbi_size; - if (next_load_addr > section_addr) { - printf("Fatal: out of memory allocating for boot metadata.\n"); - exit(1); - } - memset(mbi, 0, sizeof (struct multiboot_info)); - p = (char *)(mbi + 1); - mbi->flags = MB_INFO_CMDLINE | MB_INFO_BOOT_LOADER_NAME; - - /* Figure out the memory map. - * N.B. Must happen before place_section() is called */ - init_mmap(mbi); - - mbi_run_addr = place_low_section(mbi_size, 4); - if (mbi_run_addr == 0) { - printf("Fatal: can't find space for the MBI!\n"); - exit(1); - } - mbi_reloc_offset = (size_t)mbi - mbi_run_addr; - add_section(mbi_run_addr, (void *)mbi, mbi_size); - - /* Module info structs */ - modp = (struct mod_list *) (((size_t)p + 3) & ~3); - if (modules > 0) mbi->flags |= MB_INFO_MODS; - mbi->mods_count = modules; - mbi->mods_addr = ((size_t)modp) - mbi_reloc_offset; - p = (char *)(modp + modules); - - /* Append cmdline args show up in the beginning, append these - * to kernel cmdline later on */ - for (i = 1; i < argc; i++) { - if (strchr(argv[i], '=') != NULL) { - continue; - } - break; - } - - /* Command lines: first kernel, then modules */ - mbi->cmdline = ((size_t)p) - mbi_reloc_offset; - modules = 0; - num_append_args = i-1; - - for (; i < argc ; i++) { - if (!strcmp(argv[i], module_separator)) { - /* Add append args to kernel cmdline */ - if (modules == 0 && num_append_args) { - int j; - for (j = 1; j < num_append_args+1; j++) { - strcpy(p, argv[j]); - p += strlen(argv[j]); - *p++ = ' '; - } - } - *p++ = '\0'; - modp[modules++].cmdline = ((size_t)p) - mbi_reloc_offset; - } else { - strcpy(p, argv[i]); - p += strlen(argv[i]); - *p++ = ' '; - } - } - *p++ = '\0'; - - /* Bootloader ID */ - strcpy(p, version_string); - mbi->boot_loader_name = ((size_t)p) - mbi_reloc_offset; - p += strlen(version_string) + 1; - - if (opt_solaris) { - printf("Solaris DHCP passing enabled... "); - /* Try to get the DHCP ACK packet from PXE */ - if (!pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK, - &dhcpdata, &dhcplen)) { - /* Solaris expects the DHCP ACK packet to be passed in the drives_* - structure. However, the flags field must indicate that the - drives_structure is not being used. - Furthermore, the boot_device must be set to 0x20ffffff - */ - dhcplen = MIN(dhcplen, DHCP_ACK_SIZE); - memcpy(p, dhcpdata, dhcplen); - mbi->drives_addr = ((size_t)p) - mbi_reloc_offset; - mbi->drives_length = dhcplen; - mbi->flags &= ~MB_INFO_DRIVE_INFO; - p += dhcplen; - - mbi->boot_device = 0x20ffffff; - mbi->flags |= MB_INFO_BOOTDEV; - printf("ok\n"); - } else { - printf("not found.\n"); - } - } - - /* Now, do all the loading, and boot it */ - entry = load_kernel(mbi, (char *)(mbi->cmdline + mbi_reloc_offset)); - for (i=0; i