diff options
Diffstat (limited to 'arch/i386/boot/memory.c')
-rw-r--r-- | arch/i386/boot/memory.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/arch/i386/boot/memory.c b/arch/i386/boot/memory.c index 1a2e62db8bed..378353956b5d 100644 --- a/arch/i386/boot/memory.c +++ b/arch/i386/boot/memory.c | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | static int detect_memory_e820(void) | 21 | static int detect_memory_e820(void) |
22 | { | 22 | { |
23 | int count = 0; | ||
23 | u32 next = 0; | 24 | u32 next = 0; |
24 | u32 size, id; | 25 | u32 size, id; |
25 | u8 err; | 26 | u8 err; |
@@ -27,20 +28,33 @@ static int detect_memory_e820(void) | |||
27 | 28 | ||
28 | do { | 29 | do { |
29 | size = sizeof(struct e820entry); | 30 | size = sizeof(struct e820entry); |
30 | id = SMAP; | 31 | |
32 | /* Important: %edx is clobbered by some BIOSes, | ||
33 | so it must be either used for the error output | ||
34 | or explicitly marked clobbered. */ | ||
31 | asm("int $0x15; setc %0" | 35 | asm("int $0x15; setc %0" |
32 | : "=am" (err), "+b" (next), "+d" (id), "+c" (size), | 36 | : "=d" (err), "+b" (next), "=a" (id), "+c" (size), |
33 | "=m" (*desc) | 37 | "=m" (*desc) |
34 | : "D" (desc), "a" (0xe820)); | 38 | : "D" (desc), "d" (SMAP), "a" (0xe820)); |
39 | |||
40 | /* Some BIOSes stop returning SMAP in the middle of | ||
41 | the search loop. We don't know exactly how the BIOS | ||
42 | screwed up the map at that point, we might have a | ||
43 | partial map, the full map, or complete garbage, so | ||
44 | just return failure. */ | ||
45 | if (id != SMAP) { | ||
46 | count = 0; | ||
47 | break; | ||
48 | } | ||
35 | 49 | ||
36 | if (err || id != SMAP) | 50 | if (err) |
37 | break; | 51 | break; |
38 | 52 | ||
39 | boot_params.e820_entries++; | 53 | count++; |
40 | desc++; | 54 | desc++; |
41 | } while (next && boot_params.e820_entries < E820MAX); | 55 | } while (next && count < E820MAX); |
42 | 56 | ||
43 | return boot_params.e820_entries; | 57 | return boot_params.e820_entries = count; |
44 | } | 58 | } |
45 | 59 | ||
46 | static int detect_memory_e801(void) | 60 | static int detect_memory_e801(void) |
@@ -89,11 +103,16 @@ static int detect_memory_88(void) | |||
89 | 103 | ||
90 | int detect_memory(void) | 104 | int detect_memory(void) |
91 | { | 105 | { |
106 | int err = -1; | ||
107 | |||
92 | if (detect_memory_e820() > 0) | 108 | if (detect_memory_e820() > 0) |
93 | return 0; | 109 | err = 0; |
94 | 110 | ||
95 | if (!detect_memory_e801()) | 111 | if (!detect_memory_e801()) |
96 | return 0; | 112 | err = 0; |
113 | |||
114 | if (!detect_memory_88()) | ||
115 | err = 0; | ||
97 | 116 | ||
98 | return detect_memory_88(); | 117 | return err; |
99 | } | 118 | } |