Messages in this thread Patch in this message | | | Subject | A bios patch | Date | Thu, 19 Aug 1999 22:59:58 -0700 (PDT) |
| |
Hi, Alan,
This patch from David Parsons for 2.2.11 is needed for some Intel 440ZX MBs.
Thanks.
-- H.J. Lu (hjl@gnu.org) ----- diff -Naur linux-2.2.10-orig/arch/i386/boot/setup.S linux-2.2.10/arch/i386/boot/setup.S --- linux-2.2.10-orig/arch/i386/boot/setup.S Mon Jun 7 16:13:07 1999 +++ linux-2.2.10/arch/i386/boot/setup.S Fri Jun 18 02:14:22 1999 @@ -37,6 +37,7 @@ #include <linux/version.h> #include <linux/compile.h> #include <asm/boot.h> +#include <asm/e820.h> ! Signature words to ensure LILO loaded us right #define SIG1 0xAA55 @@ -59,7 +60,7 @@ entry start start: - jmp start_of_setup + jmp trampoline ! ------------------------ start of header -------------------------------- ! ! SETUP-header, must start at CS:2 (old 0x9020:2) @@ -119,6 +120,8 @@ heap_end_ptr: .word modelist+1024 ! space from here (exclusive) down to ! end of setup code can be used by setup ! for local heap purposes. +trampoline: call start_of_setup + .space 1024 ! ------------------------ end of header ---------------------------------- start_of_setup: @@ -245,37 +248,100 @@ loader_ok: ! Get memory size (extended mem, kB) + xor eax, eax + mov dword ptr [0x1e0], eax #ifndef STANDARD_MEMORY_BIOS_CALL - push ebx - xor ebx,ebx ! preload new memory slot with 0k - mov [0x1e0], ebx + mov dword ptr [E820MEM], eax + mov dword ptr [E820NR], eax + +! Try three different memory detection schemes. First, try +! e820h, which lets us assemble a memory map, then try e801h, +! which returns a 32-bit memory size, and finally 88h, which +! returns 0-64m + +! method E820H: +! the memory map from hell. e820h returns memory classified into +! a whole bunch of different types, and allows memory holes and +! everything. We scan through this memory map and build a list +! of the first 32 available memory areas, which we return at [0xC20]. +! We also make a stab at the memory size by the somewhat gross approach +! of setting memsize to the address+size of the LAST available memory +! we picked up. This assumes that e820 returns memory regions in strictly +! increasing order; if a bios returns those memory regions in any other +! order, we will be in for a world of pain. +! + +meme820: + mov edx, #0x534d4150 ! ascii `SMAP' + xor ebx, ebx ! continuation counter + +jmpe820: + mov eax, #0x0000e820 ! e820, upper word zeroed + mov ecx, #20 ! size of the e820rec + + mov dword ptr [E820+16], #42 + mov di, #E820 ! es:di points at the + push ds ! data record. + pop es + int 0x15 ! make the call + jc meme801 ! fall to e801 if it fails + + cmp eax, #0x534d4150 ! check the return is `SMAP' + jne meme801 ! fall to e801 if it fails + + cmp dword ptr [E820+16], #1 ! is this usable memory? + jne again820 + + ! usable memory: add it to the whitelist + ! +good820: + mov al, byte ptr [E820NR] + cmp al, #E820MAX + jnl again820 + inc byte ptr [E820NR] + and ax, #0xff ! clear sign extend + shl ax, 3 ! double dword alignment + mov si, ax + mov ecx, dword ptr [E820+8] ! pick up low dword of memsize + mov eax, dword ptr [E820+0] ! pick up low dword of address + mov E820MAP(si), eax ! store address in whitelist + mov E820MAP+4(si), ecx ! store size in whitelist + + add eax, ecx ! set end_mem to address + memsize + mov [E820MEM], eax + +again820: + cmp ebx, #0 ! check to see if ebx is + jne jmpe820 ! set to EOF - mov ax,#0xe801 - int 0x15 - jc oldstylemem -! Memory size is in 1 k chunksizes, to avoid confusing loadlin. -! We store the 0xe801 memory size in a completely different place, + +! method E801H: +! memory size is in 1k chunksizes, to avoid confusing loadlin. +! we store the 0xe801 memory size in a completely different place, ! because it will most likely be longer than 16 bits. ! (use 1e0 because that's what Larry Augustine uses in his ! alternative new memory detection scheme, and it's sensible ! to write everything into the same place.) - and ebx, #0xffff ! clear sign extend - shl ebx, 6 ! and go from 64k to 1k chunks - mov [0x1e0],ebx ! store extended memory size - - and eax, #0xffff ! clear sign extend - add [0x1e0],eax ! and add lower memory into total size. - - ! and fall into the old memory detection code to populate the - ! compatibility slot. +meme801: + + mov ax,#0xe801 + int 0x15 + jc mem88 + + and edx, #0xffff ! clear sign extend + shl edx, 6 ! and go from 64k to 1k chunks + mov [0x1e0],edx ! store extended memory size + + and ecx, #0xffff ! clear sign extend + add [0x1e0],ecx ! and add lower memory into total size. + +! Ye Olde Traditional Methode. Returns the memory size (up to 16mb or +! 64mb, depending on the bios) in ax. +mem88: -oldstylemem: - pop ebx -#else - mov dword ptr [0x1e0], #0 #endif mov ah,#0x88 int 0x15 diff -Naur linux-2.2.10-orig/arch/i386/kernel/setup.c linux-2.2.10/arch/i386/kernel/setup.c --- linux-2.2.10-orig/arch/i386/kernel/setup.c Tue Jun 8 10:43:21 1999 +++ linux-2.2.10/arch/i386/kernel/setup.c Fri Jun 18 02:53:05 1999 @@ -49,6 +49,7 @@ #include <asm/smp.h> #include <asm/cobalt.h> #include <asm/msr.h> +#include <asm/e820.h> /* * Machine setup.. @@ -82,6 +83,8 @@ unsigned char table[0]; }; +struct e820map e820 = { 0 }; + unsigned char aux_device_present; #ifdef CONFIG_BLK_DEV_RAM @@ -101,6 +104,9 @@ #define SCREEN_INFO (*(struct screen_info *) (PARAM+0)) #define EXT_MEM_K (*(unsigned short *) (PARAM+2)) #define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0)) +#define E820_MEM (*(unsigned long *) (PARAM+E820MEM)) +#define E820_MAP_NR (*(char*) (PARAM+E820NR)) +#define E820_MAP ((unsigned long *) (PARAM+E820MAP)) #define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40)) #define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80)) #define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0)) @@ -277,9 +283,27 @@ #ifndef STANDARD_MEMORY_BIOS_CALL { unsigned long memory_alt_end = (1<<20) + (ALT_MEM_K<<10); - /* printk(KERN_DEBUG "Memory sizing: %08x %08x\n", memory_end, memory_alt_end); */ + unsigned long *mem = E820_MAP; + if (memory_alt_end > memory_end) memory_end = memory_alt_end; + + if (E820_MEM > memory_end) + memory_end = E820_MEM; + + if ((e820.nr_map = E820_MAP_NR) > 0) { + int x; + + if (e820.nr_map > E820MAX) + e820.nr_map = 0; + else for (x = 0; x < e820.nr_map; x++) { + e820.map[x].addr = *(mem++); + e820.map[x].size = *(mem++); + /*printk("E820: region %d, %lu bytes @ %08lx\n", + x, e820.map[x].size, e820.map[x].addr);*/ + } + } + } #endif diff -Naur linux-2.2.10-orig/arch/i386/mm/init.c linux-2.2.10/arch/i386/mm/init.c --- linux-2.2.10-orig/arch/i386/mm/init.c Thu Jan 21 11:28:40 1999 +++ linux-2.2.10/arch/i386/mm/init.c Fri Jun 18 02:55:43 1999 @@ -27,6 +27,7 @@ #include <asm/pgtable.h> #include <asm/dma.h> #include <asm/fixmap.h> +#include <asm/e820.h> extern void show_net_buffers(void); extern unsigned long init_smp_mappings(unsigned long); @@ -390,6 +391,18 @@ int datapages = 0; int initpages = 0; unsigned long tmp; + unsigned long start_seg = 0; + unsigned long size_seg = ~0; + int nr_map = 0; + + if (nr_map < e820.nr_map) { + start_seg = e820.map[nr_map].addr + PAGE_OFFSET; + size_seg = e820.map[nr_map].size; + printk("region %d: %lu bytes @ %08lx\n", + nr_map, size_seg, start_seg - PAGE_OFFSET); + nr_map++; + } + end_mem &= PAGE_MASK; high_memory = (void *) end_mem; @@ -424,7 +437,23 @@ } while (start_mem < end_mem) { - clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags); + if (start_mem > start_seg) { + if (start_mem < start_seg + size_seg) + clear_bit(PG_reserved, + &mem_map[MAP_NR(start_mem)].flags); + else if (nr_map < e820.nr_map) { + start_seg = e820.map[nr_map].addr + PAGE_OFFSET; + size_seg = e820.map[nr_map].size; + printk("region %d: %lu bytes @ %08lx\n", + nr_map, size_seg, start_seg - PAGE_OFFSET); + nr_map++; + continue; /* be paranoid in case the */ + /* e820 code hasn't collapsed */ + /* adjacent usable memory */ + } + else + break; /* no more valid memory */ + } start_mem += PAGE_SIZE; } for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) { diff -Naur linux-2.2.10-orig/include/asm-i386/e820.h linux-2.2.10/include/asm-i386/e820.h --- linux-2.2.10-orig/include/asm-i386/e820.h Wed Dec 31 16:00:00 1969 +++ linux-2.2.10/include/asm-i386/e820.h Fri Jun 18 02:12:12 1999 @@ -0,0 +1,34 @@ +/* + * structures and definitions for the int 15, ax=e820 memory map + * scheme. + * + * In a nutshell, arch/i386/boot/setup.S populates a scratch table + * in the empty_zero_block that contains a list of usable address/size + * duples. In arch/i386/kernel/setup.c, this information is + * transferred into the e820map, and in arch/i386/mm/init.c, that + * new information is used to mark pages reserved or not. + * + */ +#ifndef __E820_HEADER +#define __E820_HEADER + +#define E820 0x2d0 /* scratch area */ +#define E820MAP 0x300 /* our map */ +#define E820MAX 32 /* number of entries in E820MAP */ +#define E820MEM 0x1e4 /* memtop from e820 calls */ +#define E820NR 0x1e8 /* # entries in E820MAP */ + +#ifndef __ASSEMBLY__ + +struct e820map { + int nr_map; + struct { + unsigned long addr; + unsigned long size; + } map[E820MAX]; +}; + +extern struct e820map e820; +#endif/*!__ASSEMBLY__*/ + +#endif/*__E820_HEADER*/
-- H.J. Lu (hjl@gnu.org)
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |