diff --git a/ChangeLog b/ChangeLog index 0682407b1..2d934c727 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2000-05-05 OKUJI Yoshinori + + Ignore any memory holes when passing the maximum memory address + to non-Multiboot kernels (i.e. Linux and *BSD). + + * stage2/common.c [!STAGE1_5] (extended_memory): New global + variable. + (init_bios_info) [!STAGE1_5]: Change the type of CONT, MEMTMP + and ADDR to unsigned long from int. + Set EXTENDED_MEMORY to MBI.MEM_UPPER by default. + If MBI.MMAP_LENGTH is not zero, set EXTENDED_MEMORY to the + maximum available address, ignoring any memory holes. + If MBI.MMAP_LENGTH is zero but get_eisamemsize returns other + than -1, set EXTENDED_MEMORY to (CONT >> 10) + 0x3c00 if CONT is + non-zero, otherwise, set it to MEMTMP. + * stage2/shared.h [!STAGE1_5] (extended_memory): Declared. + * stage2/boot.c (load_image): Always pass the "mem=" option to a + Linux kernel, using EXTENDED_MEMORY instead of MBI.MEM_UPPER. + (bsd_boot): Use EXTENDED_MEMORY instead of MBI.MEM_UPPER. + 2000-04-30 OKUJI Yoshinori * stage1/stage1.S (message): Use lodsb instead of incw and movb. diff --git a/stage2/boot.c b/stage2/boot.c index 47743bca7..e1d7b038f 100644 --- a/stage2/boot.c +++ b/stage2/boot.c @@ -276,19 +276,12 @@ load_image (char *kernel, char *arg, kernel_t suggested_type) *((unsigned short *) CL_OFFSET) = CL_MY_LOCATION - CL_BASE_ADDR; *((unsigned short *) CL_MAGIC_ADDR) = CL_MAGIC; - /* Help Linux to find memory only if more than 64MB are present. - Up to that amount it is fairly capable to find by itself, - and at least newer Phoenix BIOSes are known to put a - 10k hole just before 64MB, but report a proper total. */ - if (mbi.mem_upper + 0x400 > 0x10000) - { - grub_memmove ((char *) CL_MY_LOCATION, "mem=", 4); - dest = (char *) (CL_MY_LOCATION + 4); - - dest = convert_to_ascii (dest, 'u', (mbi.mem_upper + 0x400)); - *(dest++) = 'K'; - *(dest++) = ' '; - } + grub_memmove (dest, "mem=", 4); + dest += 4; + + dest = convert_to_ascii (dest, 'u', (extended_memory + 0x400)); + *(dest++) = 'K'; + *(dest++) = ' '; while (*src && *src != ' ') src++; @@ -696,7 +689,7 @@ bsd_boot (kernel_t type, int bootdev, char *arg) bi.bi_memsizes_valid = 1; bi.bi_bios_dev = saved_drive; bi.bi_basemem = mbi.mem_lower; - bi.bi_extmem = mbi.mem_upper; + bi.bi_extmem = extended_memory; if (mbi.flags & MB_INFO_AOUT_SYMS) { @@ -752,6 +745,6 @@ bsd_boot (kernel_t type, int bootdev, char *arg) end_mark = 0; (*entry_addr) (clval, bootdev, 0, end_mark, - mbi.mem_upper, mbi.mem_lower); + extended_memory, mbi.mem_lower); } } diff --git a/stage2/common.c b/stage2/common.c index a1a9b5be8..c3ab10f1d 100644 --- a/stage2/common.c +++ b/stage2/common.c @@ -30,6 +30,9 @@ unsigned long saved_drive; unsigned long saved_partition; #ifndef STAGE1_5 unsigned long saved_mem_upper; + +/* This saves the maximum size of extended memory (in KB). */ +unsigned long extended_memory; #endif /* @@ -98,7 +101,7 @@ void init_bios_info (void) { #ifndef STAGE1_5 - int cont, memtmp, addr; + unsigned long cont, memtmp, addr; #endif /* @@ -117,6 +120,10 @@ init_bios_info (void) gateA20 (1); + /* Store the size of extended memory in EXTENDED_MEMORY, in order to + tell it to non-Multiboot OSes. */ + extended_memory = mbi.mem_upper; + /* * The "mbi.mem_upper" variable only recognizes upper memory in the * first memory region. If there are multiple memory regions, @@ -134,11 +141,11 @@ init_bios_info (void) cont = get_mmap_entry ((void *) addr, cont); /* If the returned buffer's base is zero, quit. */ - if (!*((int *) addr)) + if (! *((unsigned long *) addr)) break; - mbi.mmap_length += *((int *) addr) + 4; - addr += *((int *) addr) + 4; + mbi.mmap_length += *((unsigned long *) addr) + 4; + addr += *((unsigned long *) addr) + 4; } while (cont); @@ -160,7 +167,7 @@ init_bios_info (void) { for (cont = 0, addr = mbi.mmap_addr; addr < mbi.mmap_addr + mbi.mmap_length; - addr += *((int *) addr) + 4) + addr += *((unsigned long *) addr) + 4) { if (((struct AddrRangeDesc *) addr)->BaseAddrHigh == 0 && ((struct AddrRangeDesc *) addr)->Type == MB_ARD_MEMORY @@ -177,19 +184,37 @@ init_bios_info (void) while (cont); mbi.mem_upper = (memtmp - 0x100000) >> 10; + + /* Find the maximum available address. Ignore any memory holes. */ + for (addr = mbi.mmap_addr; + addr < mbi.mmap_addr + mbi.mmap_length; + addr += *((unsigned long *) addr) + 4) + { + struct AddrRangeDesc *desc = (struct AddrRangeDesc *) addr; + + if (desc->BaseAddrHigh == 0 + && desc->Type == MB_ARD_MEMORY + && desc->BaseAddrLow + desc->LengthLow > extended_memory) + extended_memory = desc->BaseAddrLow + desc->LengthLow; + } } else if ((memtmp = get_eisamemsize ()) != -1) { cont = memtmp & ~0xFFFF; memtmp = memtmp & 0xFFFF; + if (cont != 0) + extended_memory = (cont >> 10) + 0x3c00; + else + extended_memory = memtmp; + if (!cont || (memtmp == 0x3c00)) memtmp += (cont >> 10); else { /* XXX should I do this at all ??? */ - mbi.mmap_addr = (int) fakemap; + mbi.mmap_addr = (unsigned long) fakemap; mbi.mmap_length = sizeof (fakemap); fakemap[0].LengthLow = (mbi.mem_lower << 10); fakemap[1].LengthLow = (memtmp << 10); diff --git a/stage2/shared.h b/stage2/shared.h index 81958abea..4279825d2 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -525,6 +525,7 @@ extern unsigned long saved_drive; extern unsigned long saved_partition; #ifndef STAGE1_5 extern unsigned long saved_mem_upper; +extern unsigned long extended_memory; #endif /*