mirror of
https://git.proxmox.com/git/grub2
synced 2025-05-18 19:17:12 +00:00

* include/pupa/i386/pc/linux.h: New file. * loader/i386/pc/linux.c: Likewise. * loader/i386/pc/chainloader.c (pupa_chainloader_boot_sector): Removed. (pupa_chainloader_unload): Return PUPA_ERR_NONE. (pupa_rescue_cmd_chainloader): Read the image to 0x7C00 instead of PUPA_CHAINLOADER_BOOT_SECTOR. * kern/i386/pc/startup.S: Include pupa/machine/linux.h. (pupa_linux_prot_size): New variable. (pupa_linux_tmp_addr): Likewise. (pupa_linux_real_addr): Likewise. (pupa_linux_boot_zimage): New function. (pupa_linux_boot_bzimage): Likewise. * kern/i386/pc/init.c (struct mem_region): New structure. (MAX_REGIONS): New macro. (mem_regions): New variable. (num_regions): Likewise. (pupa_os_area_addr): Likewise. (pupa_os_area_size): Likewise. (pupa_lower_mem): Likewise. (pupa_upper_mem): Likewise. (add_mem_region): New function. (compact_mem_regions): Likewise. (pupa_machine_init): Set PUPA_LOWER_MEM and PUPA_UPPER_MEM to the size of the conventional memory and that of so-called upper memory (before the first memory hole). Instead of adding each found region to free memory, use add_mem_region and add them after removing overlaps. Also, add only 1/4 of the upper memory to free memory. The rest is used for loading OS images. Maybe this is ad hoc, but this makes it much easier to relocate OS images when booting. * kern/rescue.c (pupa_rescue_cmd_module): Removed. (pupa_enter_rescue_mode): Don't register initrd and module. * kern/mm.c: Include pupa/dl.h. * kern/main.c: Include pupa/file.h and pupa/device.h. * kern/loader.c (pupa_loader_load_module_func): Removed. (pupa_loader_load_module): Likewise. * kern/dl.c (pupa_dl_load): Use the suffix ``.mod'' instead of ``.o''. * include/pupa/i386/pc/loader.h (pupa_linux_prot_size): Declared. (pupa_linux_tmp_addr): Likewise. (pupa_linux_real_addr): Likewise. (pupa_linux_boot_zimage): Likewise. (pupa_linux_boot_bzimage): Likewise. * include/pupa/i386/pc/init.h (pupa_lower_mem): Declared. (pupa_upper_mem): Likewise. (pupa_gate_a20): Don't export, because turning off Gate A20 in a module is too dangerous. * include/pupa/loader.h (pupa_os_area_addr): Declared. (pupa_os_area_size): Likewise. (pupa_loader_set): Remove the first argument. Loader doesn't manage modules or initrd any longer. (pupa_loader_load_module): Removed. * conf/i386-pc.rmk (pkgdata_MODULES): Added linux.mod. (linux_mod_SOURCES): New variable. (linux_mod_CFLAGS): Likewise.
154 lines
3.5 KiB
C
154 lines
3.5 KiB
C
/* chainloader.c - boot another boot loader */
|
|
/*
|
|
* PUPA -- Preliminary Universal Programming Architecture for GRUB
|
|
* Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include <pupa/loader.h>
|
|
#include <pupa/machine/loader.h>
|
|
#include <pupa/file.h>
|
|
#include <pupa/err.h>
|
|
#include <pupa/device.h>
|
|
#include <pupa/disk.h>
|
|
#include <pupa/misc.h>
|
|
#include <pupa/types.h>
|
|
#include <pupa/machine/init.h>
|
|
#include <pupa/machine/partition.h>
|
|
#include <pupa/machine/memory.h>
|
|
#include <pupa/rescue.h>
|
|
#include <pupa/dl.h>
|
|
|
|
static pupa_dl_t my_mod;
|
|
|
|
static pupa_err_t
|
|
pupa_chainloader_boot (void)
|
|
{
|
|
pupa_device_t dev;
|
|
int drive = -1;
|
|
void *part_addr = 0;
|
|
|
|
/* Open the root device. */
|
|
dev = pupa_device_open (0);
|
|
if (dev)
|
|
{
|
|
pupa_disk_t disk = dev->disk;
|
|
|
|
if (disk)
|
|
{
|
|
pupa_partition_t p = disk->partition;
|
|
|
|
/* In i386-pc, the id is equal to the BIOS drive number. */
|
|
drive = (int) disk->id;
|
|
|
|
if (p)
|
|
{
|
|
pupa_disk_read (disk, p->offset, 446, 64,
|
|
(char *) PUPA_MEMORY_MACHINE_PART_TABLE_ADDR);
|
|
|
|
/* Ignore errors. Perhaps it's not fatal. */
|
|
part_addr = (void *) (PUPA_MEMORY_MACHINE_PART_TABLE_ADDR
|
|
+ (p->index << 4));
|
|
}
|
|
}
|
|
|
|
pupa_device_close (dev);
|
|
}
|
|
|
|
pupa_chainloader_real_boot (drive, part_addr);
|
|
|
|
/* Never reach here. */
|
|
return PUPA_ERR_NONE;
|
|
}
|
|
|
|
static pupa_err_t
|
|
pupa_chainloader_unload (void)
|
|
{
|
|
pupa_dl_unref (my_mod);
|
|
return PUPA_ERR_NONE;
|
|
}
|
|
|
|
static void
|
|
pupa_rescue_cmd_chainloader (int argc, char *argv[])
|
|
{
|
|
pupa_file_t file = 0;
|
|
pupa_uint16_t signature;
|
|
int force = 0;
|
|
|
|
pupa_dl_ref (my_mod);
|
|
|
|
if (argc > 0 && pupa_strcmp (argv[0], "--force") == 0)
|
|
{
|
|
force = 1;
|
|
argc--;
|
|
argv++;
|
|
}
|
|
|
|
if (argc == 0)
|
|
{
|
|
pupa_error (PUPA_ERR_BAD_ARGUMENT, "no file specified");
|
|
goto fail;
|
|
}
|
|
|
|
file = pupa_file_open (argv[0]);
|
|
if (! file)
|
|
goto fail;
|
|
|
|
/* Read the first block. */
|
|
if (pupa_file_read (file, (char *) 0x7C00, PUPA_DISK_SECTOR_SIZE)
|
|
!= PUPA_DISK_SECTOR_SIZE)
|
|
{
|
|
if (pupa_errno == PUPA_ERR_NONE)
|
|
pupa_error (PUPA_ERR_BAD_OS, "too small");
|
|
|
|
goto fail;
|
|
}
|
|
|
|
/* Check the signature. */
|
|
signature = *((pupa_uint16_t *) (0x7C00 + PUPA_DISK_SECTOR_SIZE - 2));
|
|
if (signature != pupa_le_to_cpu16 (0xaa55) && ! force)
|
|
{
|
|
pupa_error (PUPA_ERR_BAD_OS, "invalid signature");
|
|
goto fail;
|
|
}
|
|
|
|
pupa_file_close (file);
|
|
pupa_loader_set (pupa_chainloader_boot, pupa_chainloader_unload);
|
|
return;
|
|
|
|
fail:
|
|
|
|
if (file)
|
|
pupa_file_close (file);
|
|
|
|
pupa_dl_unref (my_mod);
|
|
}
|
|
|
|
static const char loader_name[] = "chainloader";
|
|
|
|
PUPA_MOD_INIT
|
|
{
|
|
pupa_rescue_register_command (loader_name,
|
|
pupa_rescue_cmd_chainloader,
|
|
"load another boot loader");
|
|
my_mod = mod;
|
|
}
|
|
|
|
PUPA_MOD_FINI
|
|
{
|
|
pupa_rescue_unregister_command (loader_name);
|
|
}
|