2003-01-17 Yoshinori K. Okuji <okuji@enbug.org>
* 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.
This commit is contained in:
parent
a13f92373c
commit
c04da07444
17 changed files with 705 additions and 61 deletions
|
@ -28,6 +28,22 @@
|
|||
#include <pupa/err.h>
|
||||
#include <pupa/dl.h>
|
||||
#include <pupa/misc.h>
|
||||
#include <pupa/loader.h>
|
||||
|
||||
struct mem_region
|
||||
{
|
||||
pupa_addr_t addr;
|
||||
pupa_size_t size;
|
||||
};
|
||||
|
||||
#define MAX_REGIONS 32
|
||||
|
||||
static struct mem_region mem_regions[MAX_REGIONS];
|
||||
static int num_regions;
|
||||
|
||||
pupa_addr_t pupa_os_area_addr;
|
||||
pupa_size_t pupa_os_area_size;
|
||||
pupa_size_t pupa_lower_mem, pupa_upper_mem;
|
||||
|
||||
static char *
|
||||
make_install_device (void)
|
||||
|
@ -51,32 +67,79 @@ make_install_device (void)
|
|||
return pupa_prefix;
|
||||
}
|
||||
|
||||
/* Add a memory region. */
|
||||
static void
|
||||
add_mem_region (pupa_addr_t addr, pupa_size_t size)
|
||||
{
|
||||
if (num_regions == MAX_REGIONS)
|
||||
/* Ignore. */
|
||||
return;
|
||||
|
||||
mem_regions[num_regions].addr = addr;
|
||||
mem_regions[num_regions].size = size;
|
||||
num_regions++;
|
||||
}
|
||||
|
||||
/* Compact memory regions. */
|
||||
static void
|
||||
compact_mem_regions (void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
/* Sort them. */
|
||||
for (i = 0; i < num_regions - 1; i++)
|
||||
for (j = i + 1; j < num_regions; j++)
|
||||
if (mem_regions[i].addr > mem_regions[j].addr)
|
||||
{
|
||||
struct mem_region tmp = mem_regions[i];
|
||||
mem_regions[i] = mem_regions[j];
|
||||
mem_regions[j] = tmp;
|
||||
}
|
||||
|
||||
/* Merge overlaps. */
|
||||
for (i = 0; i < num_regions - 1; i++)
|
||||
if (mem_regions[i].addr + mem_regions[i].size >= mem_regions[i + 1].addr)
|
||||
{
|
||||
j = i + 1;
|
||||
|
||||
if (mem_regions[i].addr + mem_regions[i].size
|
||||
< mem_regions[j].addr + mem_regions[j].size)
|
||||
mem_regions[i].size = (mem_regions[j].addr + mem_regions[j].size
|
||||
- mem_regions[i].addr);
|
||||
|
||||
pupa_memmove (mem_regions + j, mem_regions + j + 1,
|
||||
(num_regions - j - 1) * sizeof (struct mem_region));
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pupa_machine_init (void)
|
||||
{
|
||||
pupa_uint32_t cont;
|
||||
struct pupa_machine_mmap_entry *entry
|
||||
= (struct pupa_machine_mmap_entry *) PUPA_MEMORY_MACHINE_SCRATCH_ADDR;
|
||||
pupa_size_t lower_mem = (pupa_get_memsize (0) << 10);
|
||||
pupa_addr_t end_addr = pupa_get_end_addr ();
|
||||
|
||||
int i;
|
||||
|
||||
/* Initialize the console as early as possible. */
|
||||
pupa_console_init ();
|
||||
|
||||
pupa_lower_mem = pupa_get_memsize (0) << 10;
|
||||
|
||||
/* Sanity check. */
|
||||
if (lower_mem < PUPA_MEMORY_MACHINE_RESERVED_END)
|
||||
if (pupa_lower_mem < PUPA_MEMORY_MACHINE_RESERVED_END)
|
||||
pupa_fatal ("too small memory");
|
||||
|
||||
/* Turn on Gate A20 to access >1MB. */
|
||||
pupa_gate_a20 (1);
|
||||
|
||||
/* Add the lower memory into free memory. */
|
||||
if (lower_mem >= PUPA_MEMORY_MACHINE_RESERVED_END)
|
||||
pupa_mm_init_region ((void *) PUPA_MEMORY_MACHINE_RESERVED_END,
|
||||
lower_mem - PUPA_MEMORY_MACHINE_RESERVED_END);
|
||||
if (pupa_lower_mem >= PUPA_MEMORY_MACHINE_RESERVED_END)
|
||||
add_mem_region (PUPA_MEMORY_MACHINE_RESERVED_END,
|
||||
pupa_lower_mem - PUPA_MEMORY_MACHINE_RESERVED_END);
|
||||
|
||||
pupa_mm_init_region ((void *) end_addr,
|
||||
PUPA_MEMORY_MACHINE_RESERVED_START - end_addr);
|
||||
add_mem_region (end_addr, PUPA_MEMORY_MACHINE_RESERVED_START - end_addr);
|
||||
|
||||
/* Check if pupa_get_mmap_entry works. */
|
||||
cont = pupa_get_mmap_entry (entry, 0);
|
||||
|
@ -104,7 +167,7 @@ pupa_machine_init (void)
|
|||
len = ((addr + entry->len > 0xFFFFFFFF)
|
||||
? 0xFFFFFFFF - addr
|
||||
: (pupa_size_t) entry->len);
|
||||
pupa_mm_init_region ((void *) addr, len);
|
||||
add_mem_region (addr, len);
|
||||
}
|
||||
|
||||
next:
|
||||
|
@ -121,20 +184,39 @@ pupa_machine_init (void)
|
|||
if (eisa_mmap)
|
||||
{
|
||||
if ((eisa_mmap & 0xFFFF) == 0x3C00)
|
||||
pupa_mm_init_region ((void *) 0x100000,
|
||||
(eisa_mmap << 16) + 0x100000 * 15);
|
||||
add_mem_region (0x100000, (eisa_mmap << 16) + 0x100000 * 15);
|
||||
else
|
||||
{
|
||||
pupa_mm_init_region ((void *) 0x100000,
|
||||
(eisa_mmap & 0xFFFF) << 10);
|
||||
pupa_mm_init_region ((void *) 0x1000000, eisa_mmap << 16);
|
||||
add_mem_region (0x100000, (eisa_mmap & 0xFFFF) << 10);
|
||||
add_mem_region (0x1000000, eisa_mmap << 16);
|
||||
}
|
||||
}
|
||||
else
|
||||
pupa_mm_init_region ((void *) 0x100000,
|
||||
(pupa_size_t) pupa_get_memsize (1) << 10);
|
||||
add_mem_region (0x100000, pupa_get_memsize (1) << 10);
|
||||
}
|
||||
|
||||
compact_mem_regions ();
|
||||
|
||||
/* Add the memory regions to free memory, except for the region starting
|
||||
from 1MB. This region is partially used for loading OS images.
|
||||
For now, 1/4 of this is added to free memory. */
|
||||
for (i = 0; i < num_regions; i++)
|
||||
if (mem_regions[i].addr == 0x100000)
|
||||
{
|
||||
pupa_size_t quarter = mem_regions[i].size >> 2;
|
||||
|
||||
pupa_upper_mem = mem_regions[i].size;
|
||||
pupa_os_area_addr = mem_regions[i].addr;
|
||||
pupa_os_area_size = mem_regions[i].size - quarter;
|
||||
pupa_mm_init_region ((void *) (pupa_os_area_addr + pupa_os_area_size),
|
||||
quarter);
|
||||
}
|
||||
else
|
||||
pupa_mm_init_region ((void *) mem_regions[i].addr, mem_regions[i].size);
|
||||
|
||||
if (! pupa_os_area_addr)
|
||||
pupa_fatal ("no upper memory");
|
||||
|
||||
/* The memory system was initialized, thus register built-in devices. */
|
||||
pupa_biosdisk_init ();
|
||||
|
||||
|
|
|
@ -49,7 +49,8 @@
|
|||
#include <pupa/machine/boot.h>
|
||||
#include <pupa/machine/memory.h>
|
||||
#include <pupa/machine/console.h>
|
||||
|
||||
#include <pupa/machine/linux.h>
|
||||
|
||||
#define ABS(x) ((x) - EXT_C(start) + PUPA_BOOT_MACHINE_KERNEL_ADDR + 0x200)
|
||||
|
||||
.file "startup.S"
|
||||
|
@ -282,6 +283,71 @@ FUNCTION(pupa_chainloader_real_boot)
|
|||
.code32
|
||||
|
||||
|
||||
/*
|
||||
* void pupa_linux_boot_zimage (void)
|
||||
*/
|
||||
VARIABLE(pupa_linux_prot_size)
|
||||
.long 0
|
||||
VARIABLE(pupa_linux_tmp_addr)
|
||||
.long 0
|
||||
VARIABLE(pupa_linux_real_addr)
|
||||
.long 0
|
||||
|
||||
FUNCTION(pupa_linux_boot_zimage)
|
||||
/* copy the kernel */
|
||||
movl EXT_C(pupa_linux_prot_size), %ecx
|
||||
addl $3, %ecx
|
||||
shrl $2, %ecx
|
||||
movl $PUPA_LINUX_BZIMAGE_ADDR, %esi
|
||||
movl $PUPA_LINUX_ZIMAGE_ADDR, %edi
|
||||
cld
|
||||
rep
|
||||
movsl
|
||||
|
||||
FUNCTION(pupa_linux_boot_bzimage)
|
||||
call EXT_C(pupa_dl_unload_all)
|
||||
|
||||
movl EXT_C(pupa_linux_real_addr), %ebx
|
||||
|
||||
/* copy the real mode code */
|
||||
movl EXT_C(pupa_linux_tmp_addr), %esi
|
||||
movl %ebx, %edi
|
||||
movl $PUPA_LINUX_SETUP_MOVE_SIZE, %ecx
|
||||
cld
|
||||
rep
|
||||
movsb
|
||||
|
||||
/* change %ebx to the segment address */
|
||||
shrl $4, %ebx
|
||||
movl %ebx, %eax
|
||||
addl $0x20, %eax
|
||||
movw %ax, linux_setup_seg
|
||||
|
||||
/* XXX new stack pointer in safe area for calling functions */
|
||||
movl $0x4000, %esp
|
||||
call EXT_C(pupa_stop_floppy)
|
||||
|
||||
/* final setup for linux boot */
|
||||
call prot_to_real
|
||||
.code16
|
||||
|
||||
cli
|
||||
movw %bx, %ss
|
||||
movw $PUPA_LINUX_SETUP_STACK, %sp
|
||||
|
||||
movw %bx, %ds
|
||||
movw %bx, %es
|
||||
movw %bx, %fs
|
||||
movw %bx, %gs
|
||||
|
||||
/* ljmp */
|
||||
.byte 0xea
|
||||
.word 0
|
||||
linux_setup_seg:
|
||||
.word 0
|
||||
.code32
|
||||
|
||||
|
||||
/*
|
||||
* These next two routines, "real_to_prot" and "prot_to_real" are structured
|
||||
* in a very specific way. Be very careful when changing them.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue