*** ./arch/i386/boot/setup.S~ Sun Nov 17 11:33:24 1996 --- ./arch/i386/boot/setup.S Sun Feb 21 12:58:04 1999 *************** *** 17,22 **** --- 17,26 ---- ! some changes and additional features by Christoph Niemann, ! March 1993/June 1994 (Christoph.Niemann@linux.org) ! + ! Memory detection scheme rewritten by orc@pell.chi.il.us (jessica l. + ! parsons) July 1997 (e801), Feb 1999 (e820) + ! + ! ! NOTE! These had better be the same as in bootsect.s! #define __ASSEMBLY__ *************** *** 135,143 **** ! Get memory size (extended mem, kB) ! mov ah,#0x88 ! int 0x15 ! mov [2],ax ! set the keyboard repeat rate to the max --- 139,228 ---- ! Get memory size (extended mem, kB) ! #ifndef STANDARD_MEMORY_BIOS_CALL ! xor ebx,ebx ! mov [0x1e0], ebx ! preset the e801 and e820 return areas ! mov [0x1e4], ebx ! so we don't get hilarious results when ! mov [0x1e8], ebx ! bioses don't support the memory detect ! ! calls ! ! ! 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. Currently, I don't care; I just add up all the ! ! memory and hope that no memory holes will materialize to spoil ! ! our fun. ! ! ! ! BUGS: If there's a memory hole, this method will cheerfully ignore ! ! it and keep adding up memory. It also doesn't truncate at 1mb, ! ! but adds all memory between 0k and 0xfffK in. ! ! meme820: ! mov edx, #0x534d4150 ! ascii `SMAP' ! ! ebx is the continuation counter, and it's already been zeroed ! lea di, e820rec ! es:di points at the ! ! data record. ! ! jmpe820: ! mov eax, #0x0000e820 ! e820, upper word zeroed ! mov ecx, #20 ! size of the e820rec ! ! 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 ebx, #0 ! check to see if ebx is ! je meme801 ! set to EOF ! ! cmp e820rec+0x10, #1 ! is this usable memory? ! jne jmpe820 ! no, grab the next chunk. ! ! mov eax, e820rec+8+4 ! get low dword and high ! mov ecx, e820rec+8+0 ! dword of memory size ! add [0x1e4], ecx ! and add it into our ! adc [0x1e8], eax ! long long accumulator ! ! br jmpe820 ! then go back for more. ! ! ! 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.) ! ! meme801: ! xor ecx,ecx ! use `configured memory', and pre-zero ! xor edx,edx ! the registers in case the bios lies ! ! 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: ! ! #endif ! ! mov ah,#0x88 ! int 0x15 ! mov [2],ax ! set the keyboard repeat rate to the max *************** *** 939,944 **** --- 1024,1036 ---- gdt_48: .word 0x800 ! gdt limit=2048, 256 GDT entries .word 512+gdt,0x9 ! gdt base = 0X9xxxx + + ! 0xe820 memory map block + ! + e820rec: + .word 0,0,0,0 ! base address + .word 0,0,0,0 ! length in bytes + .word 0,0 ! type of address range msg1: .ascii "Press to see SVGA-modes available, to continue or wait 30 secs." db 0x0d, 0x0a, 0x0a, 0x00 *** ./arch/i386/kernel/setup.c~ Wed Aug 16 11:53:27 1995 --- ./arch/i386/kernel/setup.c Sun Feb 21 13:00:57 1999 *************** *** 64,69 **** --- 64,71 ---- */ #define PARAM empty_zero_page #define EXT_MEM_K (*(unsigned short *) (PARAM+2)) + #define E801_MEM (*(unsigned long *) (PARAM+0x1e0)) + #define E820_MEM (*(unsigned long *) (PARAM+0x1e4)) #define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80)) #define SCREEN_INFO (*(struct screen_info *) (PARAM+0)) #define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2)) *************** *** 87,92 **** --- 89,105 ---- screen_info = SCREEN_INFO; aux_device_present = AUX_DEVICE_INFO; memory_end = (1<<20) + (EXT_MEM_K<<10); + #ifndef STANDARD_MEMORY_BIOS_CALL + { unsigned long e801_end = (1<<20) + (E801_MEM<<10); + + printk("Memory: 088: %10ld\n", memory_end); + printk("Memory: e801: %10ld\n", memory_e801_end); + printk("Memory: e820: %10ld\n", E820_MEM); + + if ((e801_end > memory_end) || (E820_MEM > memory_end)) + memory_end = (e801_end > E820_MEM) ? e801_end : E820_MEM; + } + #endif memory_end &= PAGE_MASK; ramdisk_size = RAMDISK_SIZE; #ifdef CONFIG_MAX_16M