diff options
Diffstat (limited to 'arch/i386/boot')
-rw-r--r-- | arch/i386/boot/boot.h | 24 | ||||
-rw-r--r-- | arch/i386/boot/cpucheck.c | 3 | ||||
-rw-r--r-- | arch/i386/boot/edd.c | 6 | ||||
-rw-r--r-- | arch/i386/boot/header.S | 2 | ||||
-rw-r--r-- | arch/i386/boot/memory.c | 39 | ||||
-rw-r--r-- | arch/i386/boot/pm.c | 6 | ||||
-rw-r--r-- | arch/i386/boot/tty.c | 14 | ||||
-rw-r--r-- | arch/i386/boot/video-vesa.c | 34 | ||||
-rw-r--r-- | arch/i386/boot/video-vga.c | 17 | ||||
-rw-r--r-- | arch/i386/boot/video.c | 14 |
10 files changed, 99 insertions, 60 deletions
diff --git a/arch/i386/boot/boot.h b/arch/i386/boot/boot.h index dec70c9..20bab94 100644 --- a/arch/i386/boot/boot.h +++ b/arch/i386/boot/boot.h @@ -87,7 +87,7 @@ static inline void set_fs(u16 seg) static inline u16 fs(void) { u16 seg; - asm("movw %%fs,%0" : "=rm" (seg)); + asm volatile("movw %%fs,%0" : "=rm" (seg)); return seg; } @@ -98,7 +98,7 @@ static inline void set_gs(u16 seg) static inline u16 gs(void) { u16 seg; - asm("movw %%gs,%0" : "=rm" (seg)); + asm volatile("movw %%gs,%0" : "=rm" (seg)); return seg; } @@ -107,19 +107,19 @@ typedef unsigned int addr_t; static inline u8 rdfs8(addr_t addr) { u8 v; - asm("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); + asm volatile("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); return v; } static inline u16 rdfs16(addr_t addr) { u16 v; - asm("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); + asm volatile("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); return v; } static inline u32 rdfs32(addr_t addr) { u32 v; - asm("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); + asm volatile("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); return v; } @@ -139,19 +139,19 @@ static inline void wrfs32(u32 v, addr_t addr) static inline u8 rdgs8(addr_t addr) { u8 v; - asm("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); + asm volatile("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); return v; } static inline u16 rdgs16(addr_t addr) { u16 v; - asm("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); + asm volatile("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); return v; } static inline u32 rdgs32(addr_t addr) { u32 v; - asm("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); + asm volatile("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); return v; } @@ -180,15 +180,15 @@ static inline int memcmp(const void *s1, const void *s2, size_t len) static inline int memcmp_fs(const void *s1, addr_t s2, size_t len) { u8 diff; - asm("fs; repe; cmpsb; setnz %0" - : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); + asm volatile("fs; repe; cmpsb; setnz %0" + : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); return diff; } static inline int memcmp_gs(const void *s1, addr_t s2, size_t len) { u8 diff; - asm("gs; repe; cmpsb; setnz %0" - : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); + asm volatile("gs; repe; cmpsb; setnz %0" + : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); return diff; } diff --git a/arch/i386/boot/cpucheck.c b/arch/i386/boot/cpucheck.c index 991e8ce..e655a89 100644 --- a/arch/i386/boot/cpucheck.c +++ b/arch/i386/boot/cpucheck.c @@ -96,7 +96,8 @@ static int has_fpu(void) asm volatile("movl %0,%%cr0" : : "r" (cr0)); } - asm("fninit ; fnstsw %0 ; fnstcw %1" : "+m" (fsw), "+m" (fcw)); + asm volatile("fninit ; fnstsw %0 ; fnstcw %1" + : "+m" (fsw), "+m" (fcw)); return fsw == 0 && (fcw & 0x103f) == 0x003f; } diff --git a/arch/i386/boot/edd.c b/arch/i386/boot/edd.c index 82b5c84..bd138e4 100644 --- a/arch/i386/boot/edd.c +++ b/arch/i386/boot/edd.c @@ -30,9 +30,9 @@ static int read_mbr(u8 devno, void *buf) cx = 0x0001; /* Sector 0-0-1 */ dx = devno; bx = (size_t)buf; - asm("pushfl; stc; int $0x13; setc %%al; popfl" - : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx) - : : "esi", "edi", "memory"); + asm volatile("pushfl; stc; int $0x13; setc %%al; popfl" + : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx) + : : "esi", "edi", "memory"); return -(u8)ax; /* 0 or -1 */ } diff --git a/arch/i386/boot/header.S b/arch/i386/boot/header.S index 7f4a2c5..f3140e5 100644 --- a/arch/i386/boot/header.S +++ b/arch/i386/boot/header.S @@ -275,7 +275,7 @@ die: hlt jmp die - .size die, .-due + .size die, .-die .section ".initdata", "a" setup_corrupt: diff --git a/arch/i386/boot/memory.c b/arch/i386/boot/memory.c index 1a2e62d..3783539 100644 --- a/arch/i386/boot/memory.c +++ b/arch/i386/boot/memory.c @@ -20,6 +20,7 @@ static int detect_memory_e820(void) { + int count = 0; u32 next = 0; u32 size, id; u8 err; @@ -27,20 +28,33 @@ static int detect_memory_e820(void) do { size = sizeof(struct e820entry); - id = SMAP; + + /* Important: %edx is clobbered by some BIOSes, + so it must be either used for the error output + or explicitly marked clobbered. */ asm("int $0x15; setc %0" - : "=am" (err), "+b" (next), "+d" (id), "+c" (size), + : "=d" (err), "+b" (next), "=a" (id), "+c" (size), "=m" (*desc) - : "D" (desc), "a" (0xe820)); + : "D" (desc), "d" (SMAP), "a" (0xe820)); + + /* 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 (id != SMAP) { + count = 0; + break; + } - if (err || id != SMAP) + if (err) break; - boot_params.e820_entries++; + count++; desc++; - } while (next && boot_params.e820_entries < E820MAX); + } while (next && count < E820MAX); - return boot_params.e820_entries; + return boot_params.e820_entries = count; } static int detect_memory_e801(void) @@ -89,11 +103,16 @@ static int detect_memory_88(void) int detect_memory(void) { + int err = -1; + if (detect_memory_e820() > 0) - return 0; + err = 0; if (!detect_memory_e801()) - return 0; + err = 0; + + if (!detect_memory_88()) + err = 0; - return detect_memory_88(); + return err; } diff --git a/arch/i386/boot/pm.c b/arch/i386/boot/pm.c index 6be9ca8..09fb342 100644 --- a/arch/i386/boot/pm.c +++ b/arch/i386/boot/pm.c @@ -122,7 +122,11 @@ static void setup_gdt(void) /* DS: data, read/write, 4 GB, base 0 */ [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff), }; - struct gdt_ptr gdt; + /* Xen HVM incorrectly stores a pointer to the gdt_ptr, instead + of the gdt_ptr contents. Thus, make it static so it will + stay in memory, at least long enough that we switch to the + proper kernel GDT. */ + static struct gdt_ptr gdt; gdt.len = sizeof(boot_gdt)-1; gdt.ptr = (u32)&boot_gdt + (ds() << 4); diff --git a/arch/i386/boot/tty.c b/arch/i386/boot/tty.c index 9c668aa..f3f14bd 100644 --- a/arch/i386/boot/tty.c +++ b/arch/i386/boot/tty.c @@ -54,9 +54,9 @@ static u8 gettime(void) u16 ax = 0x0200; u16 cx, dx; - asm("int $0x1a" - : "+a" (ax), "=c" (cx), "=d" (dx) - : : "ebx", "esi", "edi"); + asm volatile("int $0x1a" + : "+a" (ax), "=c" (cx), "=d" (dx) + : : "ebx", "esi", "edi"); return dx >> 8; } @@ -67,7 +67,7 @@ static u8 gettime(void) int getchar(void) { u16 ax = 0; - asm("int $0x16" : "+a" (ax)); + asm volatile("int $0x16" : "+a" (ax)); return ax & 0xff; } @@ -75,9 +75,9 @@ int getchar(void) static int kbd_pending(void) { u8 pending; - asm("int $0x16; setnz %0" - : "=rm" (pending) - : "a" (0x0100)); + asm volatile("int $0x16; setnz %0" + : "=rm" (pending) + : "a" (0x0100)); return pending; } diff --git a/arch/i386/boot/video-vesa.c b/arch/i386/boot/video-vesa.c index f1bc71e..1921907 100644 --- a/arch/i386/boot/video-vesa.c +++ b/arch/i386/boot/video-vesa.c @@ -29,7 +29,7 @@ static void vesa_store_mode_params_graphics(void); static int vesa_probe(void) { #if defined(CONFIG_VIDEO_VESA) || defined(CONFIG_FIRMWARE_EDID) - u16 ax; + u16 ax, cx, di; u16 mode; addr_t mode_ptr; struct mode_info *mi; @@ -39,9 +39,11 @@ static int vesa_probe(void) vginfo.signature = VBE2_MAGIC; - /* Optimistically assume a VESA BIOS is register-clean... */ ax = 0x4f00; - asm("int $0x10" : "+a" (ax), "=m" (vginfo) : "D" (&vginfo)); + di = (size_t)&vginfo; + asm(INT10 + : "+a" (ax), "+D" (di), "=m" (vginfo) + : : "ebx", "ecx", "edx", "esi"); if (ax != 0x004f || vginfo.signature != VESA_MAGIC || @@ -64,9 +66,11 @@ static int vesa_probe(void) memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ ax = 0x4f01; - asm("int $0x10" - : "+a" (ax), "=m" (vminfo) - : "c" (mode), "D" (&vminfo)); + cx = mode; + di = (size_t)&vminfo; + asm(INT10 + : "+a" (ax), "+c" (cx), "+D" (di), "=m" (vminfo) + : : "ebx", "edx", "esi"); if (ax != 0x004f) continue; @@ -102,16 +106,18 @@ static int vesa_probe(void) static int vesa_set_mode(struct mode_info *mode) { - u16 ax; + u16 ax, bx, cx, di; int is_graphic; u16 vesa_mode = mode->mode - VIDEO_FIRST_VESA; memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ ax = 0x4f01; - asm("int $0x10" - : "+a" (ax), "=m" (vminfo) - : "c" (vesa_mode), "D" (&vminfo)); + cx = vesa_mode; + di = (size_t)&vminfo; + asm(INT10 + : "+a" (ax), "+c" (cx), "+D" (di), "=m" (vminfo) + : : "ebx", "edx", "esi"); if (ax != 0x004f) return -1; @@ -129,9 +135,11 @@ static int vesa_set_mode(struct mode_info *mode) ax = 0x4f02; - asm volatile("int $0x10" - : "+a" (ax) - : "b" (vesa_mode), "D" (0)); + bx = vesa_mode; + di = 0; + asm volatile(INT10 + : "+a" (ax), "+b" (bx), "+D" (di) + : : "ecx", "edx", "esi"); if (ax != 0x004f) return -1; diff --git a/arch/i386/boot/video-vga.c b/arch/i386/boot/video-vga.c index 700d09a..aef02f9 100644 --- a/arch/i386/boot/video-vga.c +++ b/arch/i386/boot/video-vga.c @@ -47,16 +47,16 @@ static u8 vga_set_basic_mode(void) #ifdef CONFIG_VIDEO_400_HACK if (adapter >= ADAPTER_VGA) { - asm(INT10 - : : "a" (0x1202), "b" (0x0030) - : "ecx", "edx", "esi", "edi"); + asm volatile(INT10 + : : "a" (0x1202), "b" (0x0030) + : "ecx", "edx", "esi", "edi"); } #endif ax = 0x0f00; - asm(INT10 - : "+a" (ax) - : : "ebx", "ecx", "edx", "esi", "edi"); + asm volatile(INT10 + : "+a" (ax) + : : "ebx", "ecx", "edx", "esi", "edi"); mode = (u8)ax; @@ -73,9 +73,10 @@ static u8 vga_set_basic_mode(void) mode = 3; /* Set the mode */ + ax = mode; asm volatile(INT10 - : : "a" (mode) - : "ebx", "ecx", "edx", "esi", "edi"); + : "+a" (ax) + : : "ebx", "ecx", "edx", "esi", "edi"); do_restore = 1; return mode; } diff --git a/arch/i386/boot/video.c b/arch/i386/boot/video.c index 693f20d..e4ba897 100644 --- a/arch/i386/boot/video.c +++ b/arch/i386/boot/video.c @@ -147,7 +147,7 @@ int mode_defined(u16 mode) } /* Set mode (without recalc) */ -static int raw_set_mode(u16 mode) +static int raw_set_mode(u16 mode, u16 *real_mode) { int nmode, i; struct card_info *card; @@ -165,8 +165,10 @@ static int raw_set_mode(u16 mode) if ((mode == nmode && visible) || mode == mi->mode || - mode == (mi->y << 8)+mi->x) + mode == (mi->y << 8)+mi->x) { + *real_mode = mi->mode; return card->set_mode(mi); + } if (visible) nmode++; @@ -178,7 +180,7 @@ static int raw_set_mode(u16 mode) if (mode >= card->xmode_first && mode < card->xmode_first+card->xmode_n) { struct mode_info mix; - mix.mode = mode; + *real_mode = mix.mode = mode; mix.x = mix.y = 0; return card->set_mode(&mix); } @@ -223,6 +225,7 @@ static void vga_recalc_vertical(void) static int set_mode(u16 mode) { int rv; + u16 real_mode; /* Very special mode numbers... */ if (mode == VIDEO_CURRENT_MODE) @@ -232,13 +235,16 @@ static int set_mode(u16 mode) else if (mode == EXTENDED_VGA) mode = VIDEO_8POINT; - rv = raw_set_mode(mode); + rv = raw_set_mode(mode, &real_mode); if (rv) return rv; if (mode & VIDEO_RECALC) vga_recalc_vertical(); + /* Save the canonical mode number for the kernel, not + an alias, size specification or menu position */ + boot_params.hdr.vid_mode = real_mode; return 0; } |