![]() |
|
|||
0001 // SPDX-License-Identifier: GPL-2.0-only 0002 /* -*- linux-c -*- ------------------------------------------------------- * 0003 * 0004 * Copyright (C) 1991, 1992 Linus Torvalds 0005 * Copyright 2007 rPath, Inc. - All Rights Reserved 0006 * Copyright 2009 Intel Corporation; author H. Peter Anvin 0007 * 0008 * ----------------------------------------------------------------------- */ 0009 0010 /* 0011 * Memory detection code 0012 */ 0013 0014 #include "boot.h" 0015 0016 #define SMAP 0x534d4150 /* ASCII "SMAP" */ 0017 0018 static void detect_memory_e820(void) 0019 { 0020 int count = 0; 0021 struct biosregs ireg, oreg; 0022 struct boot_e820_entry *desc = boot_params.e820_table; 0023 static struct boot_e820_entry buf; /* static so it is zeroed */ 0024 0025 initregs(&ireg); 0026 ireg.ax = 0xe820; 0027 ireg.cx = sizeof(buf); 0028 ireg.edx = SMAP; 0029 ireg.di = (size_t)&buf; 0030 0031 /* 0032 * Note: at least one BIOS is known which assumes that the 0033 * buffer pointed to by one e820 call is the same one as 0034 * the previous call, and only changes modified fields. Therefore, 0035 * we use a temporary buffer and copy the results entry by entry. 0036 * 0037 * This routine deliberately does not try to account for 0038 * ACPI 3+ extended attributes. This is because there are 0039 * BIOSes in the field which report zero for the valid bit for 0040 * all ranges, and we don't currently make any use of the 0041 * other attribute bits. Revisit this if we see the extended 0042 * attribute bits deployed in a meaningful way in the future. 0043 */ 0044 0045 do { 0046 intcall(0x15, &ireg, &oreg); 0047 ireg.ebx = oreg.ebx; /* for next iteration... */ 0048 0049 /* BIOSes which terminate the chain with CF = 1 as opposed 0050 to %ebx = 0 don't always report the SMAP signature on 0051 the final, failing, probe. */ 0052 if (oreg.eflags & X86_EFLAGS_CF) 0053 break; 0054 0055 /* Some BIOSes stop returning SMAP in the middle of 0056 the search loop. We don't know exactly how the BIOS 0057 screwed up the map at that point, we might have a 0058 partial map, the full map, or complete garbage, so 0059 just return failure. */ 0060 if (oreg.eax != SMAP) { 0061 count = 0; 0062 break; 0063 } 0064 0065 *desc++ = buf; 0066 count++; 0067 } while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_table)); 0068 0069 boot_params.e820_entries = count; 0070 } 0071 0072 static void detect_memory_e801(void) 0073 { 0074 struct biosregs ireg, oreg; 0075 0076 initregs(&ireg); 0077 ireg.ax = 0xe801; 0078 intcall(0x15, &ireg, &oreg); 0079 0080 if (oreg.eflags & X86_EFLAGS_CF) 0081 return; 0082 0083 /* Do we really need to do this? */ 0084 if (oreg.cx || oreg.dx) { 0085 oreg.ax = oreg.cx; 0086 oreg.bx = oreg.dx; 0087 } 0088 0089 if (oreg.ax > 15*1024) { 0090 return; /* Bogus! */ 0091 } else if (oreg.ax == 15*1024) { 0092 boot_params.alt_mem_k = (oreg.bx << 6) + oreg.ax; 0093 } else { 0094 /* 0095 * This ignores memory above 16MB if we have a memory 0096 * hole there. If someone actually finds a machine 0097 * with a memory hole at 16MB and no support for 0098 * 0E820h they should probably generate a fake e820 0099 * map. 0100 */ 0101 boot_params.alt_mem_k = oreg.ax; 0102 } 0103 } 0104 0105 static void detect_memory_88(void) 0106 { 0107 struct biosregs ireg, oreg; 0108 0109 initregs(&ireg); 0110 ireg.ah = 0x88; 0111 intcall(0x15, &ireg, &oreg); 0112 0113 boot_params.screen_info.ext_mem_k = oreg.ax; 0114 } 0115 0116 void detect_memory(void) 0117 { 0118 detect_memory_e820(); 0119 0120 detect_memory_e801(); 0121 0122 detect_memory_88(); 0123 }
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |