15b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* boot.c - load and bootstrap a kernel */
25b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
35b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  GRUB  --  GRand Unified Bootloader
45b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
55b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
65b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  This program is free software; you can redistribute it and/or modify
75b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  it under the terms of the GNU General Public License as published by
85b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  the Free Software Foundation; either version 2 of the License, or
95b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  (at your option) any later version.
105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  This program is distributed in the hope that it will be useful,
125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  but WITHOUT ANY WARRANTY; without even the implied warranty of
135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  GNU General Public License for more details.
155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  You should have received a copy of the GNU General Public License
175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  along with this program; if not, write to the Free Software
185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "shared.h"
235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "freebsd.h"
255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "imgact_aout.h"
265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "i386-elf.h"
275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int cur_addr;
295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectentry_func entry_addr;
305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct mod_list mll[99];
315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int linux_mem_size;
325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  The next two functions, 'load_image' and 'load_module', are the building
355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  blocks of the multiboot loader component.  They handle essentially all
365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  of the gory details of loading in a bootable image and the modules.
375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectkernel_t
405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectload_image (char *kernel, char *arg, kernel_t suggested_type,
415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    unsigned long load_flags)
425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int len, i, exec_type = 0, align_4k = 1;
445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  entry_func real_entry_addr = 0;
455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  kernel_t type = KERNEL_TYPE_NONE;
465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  unsigned long flags = 0, text_len = 0, data_len = 0, bss_len = 0;
475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  char *str = 0, *str2 = 0;
485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  struct linux_kernel_header *lh;
495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  union
505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      struct multiboot_header *mb;
525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      struct exec *aout;
535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      Elf32_Ehdr *elf;
545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  pu;
565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* presuming that MULTIBOOT_SEARCH is large enough to encompass an
575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     executable header */
585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  unsigned char buffer[MULTIBOOT_SEARCH];
595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* sets the header pointer to point to the beginning of the
615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     buffer by default */
625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  pu.aout = (struct exec *) buffer;
635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (!grub_open (kernel))
655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return KERNEL_TYPE_NONE;
665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (!(len = grub_read (buffer, MULTIBOOT_SEARCH)) || len < 32)
685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      grub_close ();
705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (!errnum)
725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	errnum = ERR_EXEC_FORMAT;
735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return KERNEL_TYPE_NONE;
755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  for (i = 0; i < len; i++)
785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (MULTIBOOT_FOUND ((int) (buffer + i), len - i))
805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  flags = ((struct multiboot_header *) (buffer + i))->flags;
825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (flags & MULTIBOOT_UNSUPPORTED)
835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      grub_close ();
855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      errnum = ERR_BOOT_FEATURES;
865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return KERNEL_TYPE_NONE;
875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  type = KERNEL_TYPE_MULTIBOOT;
895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  str2 = "Multiboot";
905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  break;
915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* Use BUFFER as a linux kernel header, if the image is Linux zImage
955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     or bzImage.  */
965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  lh = (struct linux_kernel_header *) buffer;
975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* ELF loading supported if multiboot, FreeBSD and NetBSD.  */
995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if ((type == KERNEL_TYPE_MULTIBOOT
1005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       || pu.elf->e_ident[EI_OSABI] == ELFOSABI_FREEBSD
1015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       || grub_strcmp (pu.elf->e_ident + EI_BRAND, "FreeBSD") == 0
1025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       || suggested_type == KERNEL_TYPE_NETBSD)
1035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      && len > sizeof (Elf32_Ehdr)
1045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      && BOOTABLE_I386_ELF ((*((Elf32_Ehdr *) buffer))))
1055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
1065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (type == KERNEL_TYPE_MULTIBOOT)
1075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	entry_addr = (entry_func) pu.elf->e_entry;
1085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else
1095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	entry_addr = (entry_func) (pu.elf->e_entry & 0xFFFFFF);
1105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (entry_addr < (entry_func) 0x100000)
1125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	errnum = ERR_BELOW_1MB;
1135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* don't want to deal with ELF program header at some random
1155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         place in the file -- this generally won't happen */
1165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (pu.elf->e_phoff == 0 || pu.elf->e_phnum == 0
1175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  || ((pu.elf->e_phoff + (pu.elf->e_phentsize * pu.elf->e_phnum))
1185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      >= len))
1195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	errnum = ERR_EXEC_FORMAT;
1205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      str = "elf";
1215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (type == KERNEL_TYPE_NONE)
1235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
1245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* At the moment, there is no way to identify a NetBSD ELF
1255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     kernel, so rely on the suggested type by the user.  */
1265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (suggested_type == KERNEL_TYPE_NETBSD)
1275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
1285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      str2 = "NetBSD";
1295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      type = suggested_type;
1305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
1315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  else
1325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
1335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      str2 = "FreeBSD";
1345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      type = KERNEL_TYPE_FREEBSD;
1355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
1365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
1375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
1385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  else if (flags & MULTIBOOT_AOUT_KLUDGE)
1395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
1405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      pu.mb = (struct multiboot_header *) (buffer + i);
1415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      entry_addr = (entry_func) pu.mb->entry_addr;
1425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      cur_addr = pu.mb->load_addr;
1435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* first offset into file */
1445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      grub_seek (i - (pu.mb->header_addr - cur_addr));
1455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* If the load end address is zero, load the whole contents.  */
1475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (! pu.mb->load_end_addr)
1485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	pu.mb->load_end_addr = cur_addr + filemax;
1495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      text_len = pu.mb->load_end_addr - cur_addr;
1515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      data_len = 0;
1525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* If the bss end address is zero, assume that there is no bss area.  */
1545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (! pu.mb->bss_end_addr)
1555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	pu.mb->bss_end_addr = pu.mb->load_end_addr;
1565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      bss_len = pu.mb->bss_end_addr - pu.mb->load_end_addr;
1585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (pu.mb->header_addr < pu.mb->load_addr
1605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  || pu.mb->load_end_addr <= pu.mb->load_addr
1615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  || pu.mb->bss_end_addr < pu.mb->load_end_addr
1625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  || (pu.mb->header_addr - pu.mb->load_addr) > i)
1635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	errnum = ERR_EXEC_FORMAT;
1645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (cur_addr < 0x100000)
1665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	errnum = ERR_BELOW_1MB;
1675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      pu.aout = (struct exec *) buffer;
1695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      exec_type = 2;
1705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      str = "kludge";
1715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
1725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  else if (len > sizeof (struct exec) && !N_BADMAG ((*(pu.aout))))
1735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
1745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      entry_addr = (entry_func) pu.aout->a_entry;
1755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (type == KERNEL_TYPE_NONE)
1775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
1785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /*
1795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   *  If it doesn't have a Multiboot header, then presume
1805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   *  it is either a FreeBSD or NetBSD executable.  If so,
1815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   *  then use a magic number of normal ordering, ZMAGIC to
1825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   *  determine if it is FreeBSD.
1835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   *
1845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   *  This is all because freebsd and netbsd seem to require
1855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   *  masking out some address bits...  differently for each
1865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   *  one...  plus of course we need to know which booting
1875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   *  method to use.
1885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   */
1895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  entry_addr = (entry_func) ((int) entry_addr & 0xFFFFFF);
1905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (buffer[0] == 0xb && buffer[1] == 1)
1925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
1935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      type = KERNEL_TYPE_FREEBSD;
1945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      cur_addr = (int) entry_addr;
1955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      str2 = "FreeBSD";
1965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
1975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  else
1985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
1995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      type = KERNEL_TYPE_NETBSD;
2005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      cur_addr = (int) entry_addr & 0xF00000;
2015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (N_GETMAGIC ((*(pu.aout))) != NMAGIC)
2025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		align_4k = 0;
2035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      str2 = "NetBSD";
2045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
2055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* first offset into file */
2085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      grub_seek (N_TXTOFF (*(pu.aout)));
2095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      text_len = pu.aout->a_text;
2105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      data_len = pu.aout->a_data;
2115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      bss_len = pu.aout->a_bss;
2125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (cur_addr < 0x100000)
2145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	errnum = ERR_BELOW_1MB;
2155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      exec_type = 1;
2175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      str = "a.out";
2185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
2195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  else if (lh->boot_flag == BOOTSEC_SIGNATURE
2205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   && lh->setup_sects <= LINUX_MAX_SETUP_SECTS)
2215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
2225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      int big_linux = 0;
2235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      int setup_sects = lh->setup_sects;
2245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0200)
2265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
2275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  big_linux = (lh->loadflags & LINUX_FLAG_BIG_KERNEL);
2285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  lh->type_of_loader = LINUX_BOOT_LOADER_TYPE;
2295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Put the real mode part at as a high location as possible.  */
2315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  linux_data_real_addr
2325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    = (char *) ((mbi.mem_lower << 10) - LINUX_SETUP_MOVE_SIZE);
2335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* But it must not exceed the traditional area.  */
2345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (linux_data_real_addr > (char *) LINUX_OLD_REAL_MODE_ADDR)
2355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
2365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (lh->version >= 0x0201)
2385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
2395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
2405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      lh->loadflags |= LINUX_FLAG_CAN_USE_HEAP;
2415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
2425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (lh->version >= 0x0202)
2445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_OFFSET;
2455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  else
2465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
2475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      lh->cl_magic = LINUX_CL_MAGIC;
2485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      lh->cl_offset = LINUX_CL_OFFSET;
2495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      lh->setup_move_size = LINUX_SETUP_MOVE_SIZE;
2505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
2515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else
2535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
2545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Your kernel is quite old...  */
2555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  lh->cl_magic = LINUX_CL_MAGIC;
2565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  lh->cl_offset = LINUX_CL_OFFSET;
2575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  setup_sects = LINUX_DEFAULT_SETUP_SECTS;
2595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
2615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* If SETUP_SECTS is not set, set it to the default (4).  */
2645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (! setup_sects)
2655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	setup_sects = LINUX_DEFAULT_SETUP_SECTS;
2665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      data_len = setup_sects << 9;
2685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      text_len = filemax - data_len - SECTOR_SIZE;
2695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      linux_data_tmp_addr = (char *) LINUX_BZIMAGE_ADDR + text_len;
2715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (! big_linux
2735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  && text_len > linux_data_real_addr - (char *) LINUX_ZIMAGE_ADDR)
2745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
2755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  grub_printf (" linux 'zImage' kernel too big, try 'make bzImage'\n");
2765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  errnum = ERR_WONT_FIT;
2775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else if (linux_data_real_addr + LINUX_SETUP_MOVE_SIZE
2795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       > RAW_ADDR ((char *) (mbi.mem_lower << 10)))
2805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	errnum = ERR_WONT_FIT;
2815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else
2825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
2835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  grub_printf ("   [Linux-%s, setup=0x%x, size=0x%x]\n",
2845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       (big_linux ? "bzImage" : "zImage"), data_len, text_len);
2855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Video mode selection support. What a mess!  */
2875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* NOTE: Even the word "mess" is not still enough to
2885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     represent how wrong and bad the Linux video support is,
2895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     but I don't want to hear complaints from Linux fanatics
2905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     any more. -okuji  */
2915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  {
2925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    char *vga;
2935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    /* Find the substring "vga=".  */
2955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    vga = grub_strstr (arg, "vga=");
2965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    if (vga)
2975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      {
2985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		char *value = vga + 4;
2995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		int vid_mode;
3005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* Handle special strings.  */
3025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (substring ("normal", value) < 1)
3035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  vid_mode = LINUX_VID_MODE_NORMAL;
3045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		else if (substring ("ext", value) < 1)
3055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  vid_mode = LINUX_VID_MODE_EXTENDED;
3065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		else if (substring ("ask", value) < 1)
3075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  vid_mode = LINUX_VID_MODE_ASK;
3085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		else if (safe_parse_maxint (&value, &vid_mode))
3095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  ;
3105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		else
3115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  {
3125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    /* ERRNUM is already set inside the function
3135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       safe_parse_maxint.  */
3145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    grub_close ();
3155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    return KERNEL_TYPE_NONE;
3165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  }
3175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		lh->vid_mode = vid_mode;
3195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      }
3205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  }
3215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Check the mem= option to limit memory used for initrd.  */
3235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  {
3245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    char *mem;
3255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    mem = grub_strstr (arg, "mem=");
3275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    if (mem)
3285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      {
3295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		char *value = mem + 4;
3305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		safe_parse_maxint (&value, &linux_mem_size);
3325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		switch (errnum)
3335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  {
3345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  case ERR_NUMBER_OVERFLOW:
3355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    /* If an overflow occurs, use the maximum address for
3365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       initrd instead. This is good, because MAXINT is
3375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       greater than LINUX_INITRD_MAX_ADDRESS.  */
3385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
3395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    errnum = ERR_NONE;
3405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    break;
3415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  case ERR_NONE:
3435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    {
3445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      int shift = 0;
3455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      switch (grub_tolower (*value))
3475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			{
3485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			case 'g':
3495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			  shift += 10;
3505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			case 'm':
3515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			  shift += 10;
3525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			case 'k':
3535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			  shift += 10;
3545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			default:
3555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			  break;
3565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			}
3575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      /* Check an overflow.  */
3595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      if (linux_mem_size > (MAXINT >> shift))
3605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
3615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      else
3625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			linux_mem_size <<= shift;
3635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    }
3645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    break;
3655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  default:
3675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    linux_mem_size = 0;
3685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    errnum = ERR_NONE;
3695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    break;
3705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  }
3715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      }
3725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    else
3735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      linux_mem_size = 0;
3745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  }
3755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* It is possible that DATA_LEN + SECTOR_SIZE is greater than
3775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     MULTIBOOT_SEARCH, so the data may have been read partially.  */
3785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (data_len + SECTOR_SIZE <= MULTIBOOT_SEARCH)
3795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    grub_memmove (linux_data_tmp_addr, buffer,
3805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			  data_len + SECTOR_SIZE);
3815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  else
3825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
3835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      grub_memmove (linux_data_tmp_addr, buffer, MULTIBOOT_SEARCH);
3845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      grub_read (linux_data_tmp_addr + MULTIBOOT_SEARCH,
3855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			 data_len + SECTOR_SIZE - MULTIBOOT_SEARCH);
3865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
3875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (lh->header != LINUX_MAGIC_SIGNATURE ||
3895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      lh->version < 0x0200)
3905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    /* Clear the heap space.  */
3915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    grub_memset (linux_data_tmp_addr + ((setup_sects + 1) << 9),
3925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			 0,
3935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			 (64 - setup_sects - 1) << 9);
3945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Copy command-line plus memory hack to staging area.
3965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     NOTE: Linux has a bug that it doesn't handle multiple spaces
3975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     between two options and a space after a "mem=" option isn't
3985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     removed correctly so the arguments to init could be like
3995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     {"init", "", "", NULL}. This affects some not-very-clever
4005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     shells. Thus, the code below does a trick to avoid the bug.
4015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     That is, copy "mem=XXX" to the end of the command-line, and
4025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     avoid to copy spaces unnecessarily. Hell.  */
4035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  {
4045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    char *src = skip_to (0, arg);
4055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    char *dest = linux_data_tmp_addr + LINUX_CL_OFFSET;
4065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    while (dest < linux_data_tmp_addr + LINUX_CL_END_OFFSET && *src)
4085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      *(dest++) = *(src++);
4095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    /* Old Linux kernels have problems determining the amount of
4115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       the available memory.  To work around this problem, we add
4125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       the "mem" option to the kernel command line.  This has its
4135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       own drawbacks because newer kernels can determine the
4145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       memory map more accurately.  Boot protocol 2.03, which
4155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       appeared in Linux 2.4.18, provides a pointer to the kernel
4165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       version string, so we could check it.  But since kernel
4175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       2.4.18 and newer are known to detect memory reliably, boot
4185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       protocol 2.03 already implies that the kernel is new
4195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       enough.  The "mem" option is added if neither of the
4205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       following conditions is met:
4215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       1) The "mem" option is already present.
4225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       2) The "kernel" command is used with "--no-mem-option".
4235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       3) GNU GRUB is configured not to pass the "mem" option.
4245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	       4) The kernel supports boot protocol 2.03 or newer.  */
4255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    if (! grub_strstr (arg, "mem=")
4265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		&& ! (load_flags & KERNEL_LOAD_NO_MEM_OPTION)
4275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		&& lh->version < 0x0203		/* kernel version < 2.4.18 */
4285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		&& dest + 15 < linux_data_tmp_addr + LINUX_CL_END_OFFSET)
4295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      {
4305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*dest++ = ' ';
4315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*dest++ = 'm';
4325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*dest++ = 'e';
4335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*dest++ = 'm';
4345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*dest++ = '=';
4355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		dest = convert_to_ascii (dest, 'u', (extended_memory + 0x400));
4375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*dest++ = 'K';
4385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      }
4395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    *dest = 0;
4415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  }
4425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* offset into file */
4445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  grub_seek (data_len + SECTOR_SIZE);
4455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  cur_addr = (int) linux_data_tmp_addr + LINUX_SETUP_MOVE_SIZE;
4475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  grub_read ((char *) LINUX_BZIMAGE_ADDR, text_len);
4485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (errnum == ERR_NONE)
4505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
4515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      grub_close ();
4525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* Sanity check.  */
4545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (suggested_type != KERNEL_TYPE_NONE
4555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  && ((big_linux && suggested_type != KERNEL_TYPE_BIG_LINUX)
4565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      || (! big_linux && suggested_type != KERNEL_TYPE_LINUX)))
4575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
4585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  errnum = ERR_EXEC_FORMAT;
4595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  return KERNEL_TYPE_NONE;
4605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
4615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* Ugly hack.  */
4635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      linux_text_len = text_len;
4645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return big_linux ? KERNEL_TYPE_BIG_LINUX : KERNEL_TYPE_LINUX;
4665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
4675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  else				/* no recognizable format */
4705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    errnum = ERR_EXEC_FORMAT;
4715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* return if error */
4735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (errnum)
4745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
4755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      grub_close ();
4765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return KERNEL_TYPE_NONE;
4775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* fill the multiboot info structure */
4805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mbi.cmdline = (int) arg;
4815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mbi.mods_count = 0;
4825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mbi.mods_addr = 0;
4835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mbi.boot_device = (current_drive << 24) | current_partition;
4845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mbi.flags &= ~(MB_INFO_MODS | MB_INFO_AOUT_SYMS | MB_INFO_ELF_SHDR);
4855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mbi.syms.a.tabsize = 0;
4865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mbi.syms.a.strsize = 0;
4875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mbi.syms.a.addr = 0;
4885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mbi.syms.a.pad = 0;
4895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  printf ("   [%s-%s", str2, str);
4915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  str = "";
4935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (exec_type)		/* can be loaded like a.out */
4955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
4965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (flags & MULTIBOOT_AOUT_KLUDGE)
4975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	str = "-and-data";
4985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      printf (", loadaddr=0x%x, text%s=0x%x", cur_addr, str, text_len);
5005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* read text, then read data */
5025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (grub_read ((char *) RAW_ADDR (cur_addr), text_len) == text_len)
5035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
5045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  cur_addr += text_len;
5055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (!(flags & MULTIBOOT_AOUT_KLUDGE))
5075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
5085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* we have to align to a 4K boundary */
5095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (align_4k)
5105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
5115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      else
5125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		printf (", C");
5135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      printf (", data=0x%x", data_len);
5155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if ((grub_read ((char *) RAW_ADDR (cur_addr), data_len)
5175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		   != data_len)
5185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  && !errnum)
5195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		errnum = ERR_EXEC_FORMAT;
5205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      cur_addr += data_len;
5215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
5225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (!errnum)
5245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
5255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      memset ((char *) RAW_ADDR (cur_addr), 0, bss_len);
5265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      cur_addr += bss_len;
5275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      printf (", bss=0x%x", bss_len);
5295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
5305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else if (!errnum)
5325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	errnum = ERR_EXEC_FORMAT;
5335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (!errnum && pu.aout->a_syms
5355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  && pu.aout->a_syms < (filemax - filepos))
5365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
5375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  int symtab_err, orig_addr = cur_addr;
5385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* we should align to a 4K boundary here for good measure */
5405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (align_4k)
5415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
5425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  mbi.syms.a.addr = cur_addr;
5445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  *((int *) RAW_ADDR (cur_addr)) = pu.aout->a_syms;
5465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  cur_addr += sizeof (int);
5475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  printf (", symtab=0x%x", pu.aout->a_syms);
5495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (grub_read ((char *) RAW_ADDR (cur_addr), pu.aout->a_syms)
5515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      == pu.aout->a_syms)
5525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
5535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      cur_addr += pu.aout->a_syms;
5545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      mbi.syms.a.tabsize = pu.aout->a_syms;
5555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (grub_read ((char *) &i, sizeof (int)) == sizeof (int))
5575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
5585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  *((int *) RAW_ADDR (cur_addr)) = i;
5595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  cur_addr += sizeof (int);
5605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  mbi.syms.a.strsize = i;
5625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  i -= sizeof (int);
5645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  printf (", strtab=0x%x", i);
5665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  symtab_err = (grub_read ((char *) RAW_ADDR (cur_addr), i)
5685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				!= i);
5695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  cur_addr += i;
5705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
5715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      else
5725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		symtab_err = 1;
5735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
5745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  else
5755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    symtab_err = 1;
5765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (symtab_err)
5785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
5795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      printf ("(bad)");
5805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      cur_addr = orig_addr;
5815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      mbi.syms.a.tabsize = 0;
5825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      mbi.syms.a.strsize = 0;
5835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      mbi.syms.a.addr = 0;
5845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
5855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  else
5865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    mbi.flags |= MB_INFO_AOUT_SYMS;
5875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
5895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  else
5905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* ELF executable */
5915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
5925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      unsigned loaded = 0, memaddr, memsiz, filesiz;
5935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      Elf32_Phdr *phdr;
5945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* reset this to zero for now */
5965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      cur_addr = 0;
5975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* scan for program segments */
5995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      for (i = 0; i < pu.elf->e_phnum; i++)
6005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
6015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  phdr = (Elf32_Phdr *)
6025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    (pu.elf->e_phoff + ((int) buffer)
6035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     + (pu.elf->e_phentsize * i));
6045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (phdr->p_type == PT_LOAD)
6055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
6065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* offset into file */
6075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      grub_seek (phdr->p_offset);
6085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      filesiz = phdr->p_filesz;
6095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (type == KERNEL_TYPE_FREEBSD || type == KERNEL_TYPE_NETBSD)
6115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		memaddr = RAW_ADDR (phdr->p_paddr & 0xFFFFFF);
6125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      else
6135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		memaddr = RAW_ADDR (phdr->p_paddr);
6145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      memsiz = phdr->p_memsz;
6165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (memaddr < RAW_ADDR (0x100000))
6175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		errnum = ERR_BELOW_1MB;
6185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* If the memory range contains the entry address, get the
6205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		 physical address here.  */
6215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (type == KERNEL_TYPE_MULTIBOOT
6225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  && (unsigned) entry_addr >= phdr->p_vaddr
6235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  && (unsigned) entry_addr < phdr->p_vaddr + memsiz)
6245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		real_entry_addr = (entry_func) ((unsigned) entry_addr
6255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project						+ memaddr - phdr->p_vaddr);
6265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* make sure we only load what we're supposed to! */
6285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (filesiz > memsiz)
6295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		filesiz = memsiz;
6305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* mark memory as used */
6315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (cur_addr < memaddr + memsiz)
6325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		cur_addr = memaddr + memsiz;
6335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      printf (", <0x%x:0x%x:0x%x>", memaddr, filesiz,
6345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      memsiz - filesiz);
6355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* increment number of segments */
6365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      loaded++;
6375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* load the segment */
6395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (memcheck (memaddr, memsiz)
6405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  && grub_read ((char *) memaddr, filesiz) == filesiz)
6415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
6425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  if (memsiz > filesiz)
6435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    memset ((char *) (memaddr + filesiz), 0, memsiz - filesiz);
6445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
6455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      else
6465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		break;
6475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
6485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
6495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (! errnum)
6515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
6525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (! loaded)
6535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    errnum = ERR_EXEC_FORMAT;
6545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  else
6555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
6565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* Load ELF symbols.  */
6575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      Elf32_Shdr *shdr = NULL;
6585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      int tab_size, sec_size;
6595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      int symtab_err = 0;
6605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      mbi.syms.e.num = pu.elf->e_shnum;
6625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      mbi.syms.e.size = pu.elf->e_shentsize;
6635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      mbi.syms.e.shndx = pu.elf->e_shstrndx;
6645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* We should align to a 4K boundary here for good measure.  */
6665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (align_4k)
6675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
6685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      tab_size = pu.elf->e_shentsize * pu.elf->e_shnum;
6705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      grub_seek (pu.elf->e_shoff);
6725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (grub_read ((char *) RAW_ADDR (cur_addr), tab_size)
6735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  == tab_size)
6745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
6755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  mbi.syms.e.addr = cur_addr;
6765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  shdr = (Elf32_Shdr *) mbi.syms.e.addr;
6775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  cur_addr += tab_size;
6785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  printf (", shtab=0x%x", cur_addr);
6805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  for (i = 0; i < mbi.syms.e.num; i++)
6825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    {
6835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      /* This section is a loaded section,
6845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			 so we don't care.  */
6855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      if (shdr[i].sh_addr != 0)
6865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			continue;
6875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      /* This section is empty, so we don't care.  */
6895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      if (shdr[i].sh_size == 0)
6905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			continue;
6915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      /* Align the section to a sh_addralign bits boundary.  */
6935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      cur_addr = ((cur_addr + shdr[i].sh_addralign) &
6945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				  - (int) shdr[i].sh_addralign);
6955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      grub_seek (shdr[i].sh_offset);
6975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      sec_size = shdr[i].sh_size;
6995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      if (! (memcheck (cur_addr, sec_size)
7015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			     && (grub_read ((char *) RAW_ADDR (cur_addr),
7025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					    sec_size)
7035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				 == sec_size)))
7045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			{
7055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			  symtab_err = 1;
7065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			  break;
7075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			}
7085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      shdr[i].sh_addr = cur_addr;
7105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      cur_addr += sec_size;
7115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    }
7125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
7135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      else
7145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		symtab_err = 1;
7155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (mbi.syms.e.addr < RAW_ADDR(0x10000))
7175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		symtab_err = 1;
7185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (symtab_err)
7205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
7215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  printf ("(bad)");
7225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  mbi.syms.e.num = 0;
7235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  mbi.syms.e.size = 0;
7245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  mbi.syms.e.addr = 0;
7255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  mbi.syms.e.shndx = 0;
7265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  cur_addr = 0;
7275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
7285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      else
7295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		mbi.flags |= MB_INFO_ELF_SHDR;
7305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
7315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
7325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
7335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (! errnum)
7355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
7365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      grub_printf (", entry=0x%x]\n", (unsigned) entry_addr);
7375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* If the entry address is physically different from that of the ELF
7395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 header, correct it here.  */
7405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (real_entry_addr)
7415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	entry_addr = real_entry_addr;
7425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
7435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  else
7445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
7455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      putchar ('\n');
7465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      type = KERNEL_TYPE_NONE;
7475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
7485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  grub_close ();
7505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* Sanity check.  */
7525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (suggested_type != KERNEL_TYPE_NONE && suggested_type != type)
7535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
7545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      errnum = ERR_EXEC_FORMAT;
7555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return KERNEL_TYPE_NONE;
7565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
7575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return type;
7595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
7605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
7625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectload_module (char *module, char *arg)
7635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
7645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int len;
7655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* if we are supposed to load on 4K boundaries */
7675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
7685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (!grub_open (module))
7705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return 0;
7715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  len = grub_read ((char *) cur_addr, -1);
7735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (! len)
7745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
7755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      grub_close ();
7765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return 0;
7775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
7785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  printf ("   [Multiboot-module @ 0x%x, 0x%x bytes]\n", cur_addr, len);
7805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* these two simply need to be set if any modules are loaded at all */
7825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mbi.flags |= MB_INFO_MODS;
7835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mbi.mods_addr = (int) mll;
7845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mll[mbi.mods_count].cmdline = (int) arg;
7865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mll[mbi.mods_count].mod_start = cur_addr;
7875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  cur_addr += len;
7885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mll[mbi.mods_count].mod_end = cur_addr;
7895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mll[mbi.mods_count].pad = 0;
7905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* increment number of modules included */
7925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mbi.mods_count++;
7935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  grub_close ();
7955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return 1;
7965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
7975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
7995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectload_initrd (char *initrd)
8005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
8015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int len;
8025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  unsigned long moveto;
8035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  unsigned long max_addr;
8045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  struct linux_kernel_header *lh
8055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    = (struct linux_kernel_header *) (cur_addr - LINUX_SETUP_MOVE_SIZE);
8065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifndef NO_DECOMPRESSION
8085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  no_decompression = 1;
8095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
8105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (! grub_open (initrd))
8125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    goto fail;
8135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  len = grub_read ((char *) cur_addr, -1);
8155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (! len)
8165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
8175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      grub_close ();
8185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      goto fail;
8195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
8205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (linux_mem_size)
8225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    moveto = linux_mem_size;
8235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  else
8245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    moveto = (mbi.mem_upper + 0x400) << 10;
8255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  moveto = (moveto - len) & 0xfffff000;
8275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203
8285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS);
8295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (moveto + len >= max_addr)
8305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    moveto = (max_addr - len) & 0xfffff000;
8315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid
8335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     the last page.
8345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     XXX: Linux 2.2.xx has a bug in the memory range check, which is
8355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     worse than that of Linux 2.3.xx, so avoid the last 64kb. *sigh*  */
8365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  moveto -= 0x10000;
8375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, len);
8385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  printf ("   [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len);
8405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* FIXME: Should check if the kernel supports INITRD.  */
8425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  lh->ramdisk_image = RAW_ADDR (moveto);
8435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  lh->ramdisk_size = len;
8445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  grub_close ();
8465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project fail:
8485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifndef NO_DECOMPRESSION
8505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  no_decompression = 0;
8515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
8525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return ! errnum;
8545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
8555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef GRUB_UTIL
8585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Dummy function to fake the *BSD boot.  */
8595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void
8605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectbsd_boot_entry (int flags, int bootdev, int sym_start, int sym_end,
8615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		int mem_upper, int mem_lower)
8625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
8635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  stop ();
8645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
8655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
8665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
8695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  All "*_boot" commands depend on the images being loaded into memory
8705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  correctly, the variables in this file being set up correctly, and
8715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  the root partition being set in the 'saved_drive' and 'saved_partition'
8725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  variables.
8735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
8745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectvoid
8775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectbsd_boot (kernel_t type, int bootdev, char *arg)
8785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
8795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  char *str;
8805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int clval = 0, i;
8815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  struct bootinfo bi;
8825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef GRUB_UTIL
8845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  entry_addr = (entry_func) bsd_boot_entry;
8855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
8865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  stop_floppy ();
8875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
8885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  while (*(++arg) && *arg != ' ');
8905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  str = arg;
8915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  while (*str)
8925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
8935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (*str == '-')
8945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
8955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  while (*str && *str != ' ')
8965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
8975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (*str == 'C')
8985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		clval |= RB_CDROM;
8995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (*str == 'a')
9005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		clval |= RB_ASKNAME;
9015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (*str == 'b')
9025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		clval |= RB_HALT;
9035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (*str == 'c')
9045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		clval |= RB_CONFIG;
9055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (*str == 'd')
9065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		clval |= RB_KDB;
9075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (*str == 'D')
9085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		clval |= RB_MULTIPLE;
9095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (*str == 'g')
9105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		clval |= RB_GDB;
9115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (*str == 'h')
9125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		clval |= RB_SERIAL;
9135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (*str == 'm')
9145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		clval |= RB_MUTE;
9155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (*str == 'r')
9165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		clval |= RB_DFLTROOT;
9175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (*str == 's')
9185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		clval |= RB_SINGLE;
9195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (*str == 'v')
9205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		clval |= RB_VERBOSE;
9215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      str++;
9225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
9235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  continue;
9245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
9255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      str++;
9265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
9275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (type == KERNEL_TYPE_FREEBSD)
9295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
9305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      clval |= RB_BOOTINFO;
9315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      bi.bi_version = BOOTINFO_VERSION;
9335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      *arg = 0;
9355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      while ((--arg) > (char *) MB_CMDLINE_BUF && *arg != '/');
9365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (*arg == '/')
9375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	bi.bi_kernelname = arg + 1;
9385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else
9395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	bi.bi_kernelname = 0;
9405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      bi.bi_nfs_diskless = 0;
9425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      bi.bi_n_bios_used = 0;	/* this field is apparently unused */
9435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      for (i = 0; i < N_BIOS_GEOM; i++)
9455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
9465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  struct geometry geom;
9475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* XXX Should check the return value.  */
9495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  get_diskinfo (i + 0x80, &geom);
9505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* FIXME: If HEADS or SECTORS is greater than 255, then this will
9515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     break the geometry information. That is a drawback of BSD
9525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     but not of GRUB.  */
9535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  bi.bi_bios_geom[i] = (((geom.cylinders - 1) << 16)
9545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				+ (((geom.heads - 1) & 0xff) << 8)
9555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				+ (geom.sectors & 0xff));
9565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
9575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      bi.bi_size = sizeof (struct bootinfo);
9595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      bi.bi_memsizes_valid = 1;
9605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      bi.bi_bios_dev = saved_drive;
9615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      bi.bi_basemem = mbi.mem_lower;
9625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      bi.bi_extmem = extended_memory;
9635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (mbi.flags & MB_INFO_AOUT_SYMS)
9655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
9665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  bi.bi_symtab = mbi.syms.a.addr;
9675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  bi.bi_esymtab = mbi.syms.a.addr + 4
9685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    + mbi.syms.a.tabsize + mbi.syms.a.strsize;
9695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
9705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if 0
9715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else if (mbi.flags & MB_INFO_ELF_SHDR)
9725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
9735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* FIXME: Should check if a symbol table exists and, if exists,
9745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     pass the table to BI.  */
9755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
9765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
9775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else
9785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
9795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  bi.bi_symtab = 0;
9805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  bi.bi_esymtab = 0;
9815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
9825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* call entry point */
9845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      (*entry_addr) (clval, bootdev, 0, 0, 0, ((int) (&bi)));
9855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
9865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  else
9875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
9885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /*
9895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *  We now pass the various bootstrap parameters to the loaded
9905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *  image via the argument list.
9915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *
9925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *  This is the official list:
9935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *
9945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *  arg0 = 8 (magic)
9955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *  arg1 = boot flags
9965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *  arg2 = boot device
9975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *  arg3 = start of symbol table (0 if not loaded)
9985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *  arg4 = end of symbol table (0 if not loaded)
9995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *  arg5 = transfer address from image
10005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *  arg6 = transfer address for next image pointer
10015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *  arg7 = conventional memory size (640)
10025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *  arg8 = extended memory size (8196)
10035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *
10045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       *  ...in actuality, we just pass the parameters used by the kernel.
10055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       */
10065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* call entry point */
10085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      unsigned long end_mark;
10095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (mbi.flags & MB_INFO_AOUT_SYMS)
10115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	end_mark = (mbi.syms.a.addr + 4
10125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    + mbi.syms.a.tabsize + mbi.syms.a.strsize);
10135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else
10145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* FIXME: it should be mbi.syms.e.size.  */
10155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	end_mark = 0;
10165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      (*entry_addr) (clval, bootdev, 0, end_mark,
10185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		     extended_memory, mbi.mem_lower);
10195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
10205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
1021