diff options
Diffstat (limited to 'arch/x86/boot')
-rw-r--r-- | arch/x86/boot/memory.c | 29 |
1 files changed, 13 insertions, 16 deletions
diff --git a/arch/x86/boot/memory.c b/arch/x86/boot/memory.c index d989de810cac..cae3feb1035e 100644 --- a/arch/x86/boot/memory.c +++ b/arch/x86/boot/memory.c | |||
@@ -17,17 +17,12 @@ | |||
17 | 17 | ||
18 | #define SMAP 0x534d4150 /* ASCII "SMAP" */ | 18 | #define SMAP 0x534d4150 /* ASCII "SMAP" */ |
19 | 19 | ||
20 | struct e820_ext_entry { | ||
21 | struct e820entry std; | ||
22 | u32 ext_flags; | ||
23 | } __attribute__((packed)); | ||
24 | |||
25 | static int detect_memory_e820(void) | 20 | static int detect_memory_e820(void) |
26 | { | 21 | { |
27 | int count = 0; | 22 | int count = 0; |
28 | struct biosregs ireg, oreg; | 23 | struct biosregs ireg, oreg; |
29 | struct e820entry *desc = boot_params.e820_map; | 24 | struct e820entry *desc = boot_params.e820_map; |
30 | static struct e820_ext_entry buf; /* static so it is zeroed */ | 25 | static struct e820entry buf; /* static so it is zeroed */ |
31 | 26 | ||
32 | initregs(&ireg); | 27 | initregs(&ireg); |
33 | ireg.ax = 0xe820; | 28 | ireg.ax = 0xe820; |
@@ -36,10 +31,18 @@ static int detect_memory_e820(void) | |||
36 | ireg.di = (size_t)&buf; | 31 | ireg.di = (size_t)&buf; |
37 | 32 | ||
38 | /* | 33 | /* |
39 | * Set this here so that if the BIOS doesn't change this field | 34 | * Note: at least one BIOS is known which assumes that the |
40 | * but still doesn't change %ecx, we're still okay... | 35 | * buffer pointed to by one e820 call is the same one as |
36 | * the previous call, and only changes modified fields. Therefore, | ||
37 | * we use a temporary buffer and copy the results entry by entry. | ||
38 | * | ||
39 | * This routine deliberately does not try to account for | ||
40 | * ACPI 3+ extended attributes. This is because there are | ||
41 | * BIOSes in the field which report zero for the valid bit for | ||
42 | * all ranges, and we don't currently make any use of the | ||
43 | * other attribute bits. Revisit this if we see the extended | ||
44 | * attribute bits deployed in a meaningful way in the future. | ||
41 | */ | 45 | */ |
42 | buf.ext_flags = 1; | ||
43 | 46 | ||
44 | do { | 47 | do { |
45 | intcall(0x15, &ireg, &oreg); | 48 | intcall(0x15, &ireg, &oreg); |
@@ -61,13 +64,7 @@ static int detect_memory_e820(void) | |||
61 | break; | 64 | break; |
62 | } | 65 | } |
63 | 66 | ||
64 | /* ACPI 3.0 added the extended flags support. If bit 0 | 67 | *desc++ = buf; |
65 | in the extended flags is zero, we're supposed to simply | ||
66 | ignore the entry -- a backwards incompatible change! */ | ||
67 | if (oreg.cx > 20 && !(buf.ext_flags & 1)) | ||
68 | continue; | ||
69 | |||
70 | *desc++ = buf.std; | ||
71 | count++; | 68 | count++; |
72 | } while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map)); | 69 | } while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map)); |
73 | 70 | ||