123 lines · 3.1 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* -*- linux-c -*- ------------------------------------------------------- * * *   Copyright (C) 1991, 1992 Linus Torvalds *   Copyright 2007 rPath, Inc. - All Rights Reserved *   Copyright 2009 Intel Corporation; author H. Peter Anvin * * ----------------------------------------------------------------------- */ /* * Memory detection code */ #include "boot.h" #define SMAP	0x534d4150	/* ASCII "SMAP" */ static void detect_memory_e820(void){	int count = 0;	struct biosregs ireg, oreg;	struct boot_e820_entry *desc = boot_params.e820_table;	static struct boot_e820_entry buf; /* static so it is zeroed */ 	initregs(&ireg);	ireg.ax  = 0xe820;	ireg.cx  = sizeof(buf);	ireg.edx = SMAP;	ireg.di  = (size_t)&buf; 	/*	 * Note: at least one BIOS is known which assumes that the	 * buffer pointed to by one e820 call is the same one as	 * the previous call, and only changes modified fields.  Therefore,	 * we use a temporary buffer and copy the results entry by entry.	 *	 * This routine deliberately does not try to account for	 * ACPI 3+ extended attributes.  This is because there are	 * BIOSes in the field which report zero for the valid bit for	 * all ranges, and we don't currently make any use of the	 * other attribute bits.  Revisit this if we see the extended	 * attribute bits deployed in a meaningful way in the future.	 */ 	do {		intcall(0x15, &ireg, &oreg);		ireg.ebx = oreg.ebx; /* for next iteration... */ 		/* BIOSes which terminate the chain with CF = 1 as opposed		   to %ebx = 0 don't always report the SMAP signature on		   the final, failing, probe. */		if (oreg.eflags & X86_EFLAGS_CF)			break; 		/* Some BIOSes stop returning SMAP in the middle of		   the search loop.  We don't know exactly how the BIOS		   screwed up the map at that point, we might have a		   partial map, the full map, or complete garbage, so		   just return failure. */		if (oreg.eax != SMAP) {			count = 0;			break;		} 		*desc++ = buf;		count++;	} while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_table)); 	boot_params.e820_entries = count;} static void detect_memory_e801(void){	struct biosregs ireg, oreg; 	initregs(&ireg);	ireg.ax = 0xe801;	intcall(0x15, &ireg, &oreg); 	if (oreg.eflags & X86_EFLAGS_CF)		return; 	/* Do we really need to do this? */	if (oreg.cx || oreg.dx) {		oreg.ax = oreg.cx;		oreg.bx = oreg.dx;	} 	if (oreg.ax > 15*1024) {		return;	/* Bogus! */	} else if (oreg.ax == 15*1024) {		boot_params.alt_mem_k = (oreg.bx << 6) + oreg.ax;	} else {		/*		 * This ignores memory above 16MB if we have a memory		 * hole there.  If someone actually finds a machine		 * with a memory hole at 16MB and no support for		 * 0E820h they should probably generate a fake e820		 * map.		 */		boot_params.alt_mem_k = oreg.ax;	}} static void detect_memory_88(void){	struct biosregs ireg, oreg; 	initregs(&ireg);	ireg.ah = 0x88;	intcall(0x15, &ireg, &oreg); 	boot_params.screen_info.ext_mem_k = oreg.ax;} void detect_memory(void){	detect_memory_e820(); 	detect_memory_e801(); 	detect_memory_88();}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t