diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-26 16:56:01 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-26 16:56:01 -0400 |
| commit | 26adc0d5859788b74f86677538236f807e6d9021 (patch) | |
| tree | 78b3c4018161d72b6d8d1f2485c52fc552caa61a | |
| parent | 0e4bd10c9b7e9ed65132f5935328275deb760384 (diff) | |
| parent | e6e1ace9904b72478f0c5a5aa7bd174cb6f62561 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hpa/linux-2.6-x86setup
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hpa/linux-2.6-x86setup:
x86 setup: sizeof() is unsigned, unbreak comparisons
x86 setup: handle boot loaders which set up the stack incorrectly
| -rw-r--r-- | arch/x86/boot/boot.h | 8 | ||||
| -rw-r--r-- | arch/x86/boot/header.S | 62 | ||||
| -rw-r--r-- | arch/x86/boot/video-bios.c | 2 | ||||
| -rw-r--r-- | arch/x86/boot/video-vesa.c | 2 | ||||
| -rw-r--r-- | arch/x86/boot/video.c | 2 |
5 files changed, 51 insertions, 25 deletions
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h index 5f9a2e72a731..d2b5adf46512 100644 --- a/arch/x86/boot/boot.h +++ b/arch/x86/boot/boot.h | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | #ifndef BOOT_BOOT_H | 17 | #ifndef BOOT_BOOT_H |
| 18 | #define BOOT_BOOT_H | 18 | #define BOOT_BOOT_H |
| 19 | 19 | ||
| 20 | #define STACK_SIZE 512 /* Minimum number of bytes for stack */ | ||
| 21 | |||
| 20 | #ifndef __ASSEMBLY__ | 22 | #ifndef __ASSEMBLY__ |
| 21 | 23 | ||
| 22 | #include <stdarg.h> | 24 | #include <stdarg.h> |
| @@ -198,8 +200,6 @@ static inline int isdigit(int ch) | |||
| 198 | } | 200 | } |
| 199 | 201 | ||
| 200 | /* Heap -- available for dynamic lists. */ | 202 | /* Heap -- available for dynamic lists. */ |
| 201 | #define STACK_SIZE 512 /* Minimum number of bytes for stack */ | ||
| 202 | |||
| 203 | extern char _end[]; | 203 | extern char _end[]; |
| 204 | extern char *HEAP; | 204 | extern char *HEAP; |
| 205 | extern char *heap_end; | 205 | extern char *heap_end; |
| @@ -216,9 +216,9 @@ static inline char *__get_heap(size_t s, size_t a, size_t n) | |||
| 216 | #define GET_HEAP(type, n) \ | 216 | #define GET_HEAP(type, n) \ |
| 217 | ((type *)__get_heap(sizeof(type),__alignof__(type),(n))) | 217 | ((type *)__get_heap(sizeof(type),__alignof__(type),(n))) |
| 218 | 218 | ||
| 219 | static inline int heap_free(void) | 219 | static inline bool heap_free(size_t n) |
| 220 | { | 220 | { |
| 221 | return heap_end-HEAP; | 221 | return (int)(heap_end-HEAP) >= (int)n; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | /* copy.S */ | 224 | /* copy.S */ |
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 8353c81c41c0..6ef5a060fa11 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S | |||
| @@ -173,7 +173,8 @@ ramdisk_size: .long 0 # its size in bytes | |||
| 173 | bootsect_kludge: | 173 | bootsect_kludge: |
| 174 | .long 0 # obsolete | 174 | .long 0 # obsolete |
| 175 | 175 | ||
| 176 | heap_end_ptr: .word _end+1024 # (Header version 0x0201 or later) | 176 | heap_end_ptr: .word _end+STACK_SIZE-512 |
| 177 | # (Header version 0x0201 or later) | ||
| 177 | # space from here (exclusive) down to | 178 | # space from here (exclusive) down to |
| 178 | # end of setup code can be used by setup | 179 | # end of setup code can be used by setup |
| 179 | # for local heap purposes. | 180 | # for local heap purposes. |
| @@ -230,28 +231,53 @@ start_of_setup: | |||
| 230 | int $0x13 | 231 | int $0x13 |
| 231 | #endif | 232 | #endif |
| 232 | 233 | ||
| 233 | # We will have entered with %cs = %ds+0x20, normalize %cs so | ||
| 234 | # it is on par with the other segments. | ||
| 235 | pushw %ds | ||
| 236 | pushw $setup2 | ||
| 237 | lretw | ||
| 238 | |||
| 239 | setup2: | ||
| 240 | # Force %es = %ds | 234 | # Force %es = %ds |
| 241 | movw %ds, %ax | 235 | movw %ds, %ax |
| 242 | movw %ax, %es | 236 | movw %ax, %es |
| 243 | cld | 237 | cld |
| 244 | 238 | ||
| 245 | # Stack paranoia: align the stack and make sure it is good | 239 | # Apparently some ancient versions of LILO invoked the kernel |
| 246 | # for both 16- and 32-bit references. In particular, if we | 240 | # with %ss != %ds, which happened to work by accident for the |
| 247 | # were meant to have been using the full 16-bit segment, the | 241 | # old code. If the CAN_USE_HEAP flag is set in loadflags, or |
| 248 | # caller might have set %sp to zero, which breaks %esp-based | 242 | # %ss != %ds, then adjust the stack pointer. |
| 249 | # references. | 243 | |
| 250 | andw $~3, %sp # dword align (might as well...) | 244 | # Smallest possible stack we can tolerate |
| 251 | jnz 1f | 245 | movw $(_end+STACK_SIZE), %cx |
| 252 | movw $0xfffc, %sp # Make sure we're not zero | 246 | |
| 253 | 1: movzwl %sp, %esp # Clear upper half of %esp | 247 | movw heap_end_ptr, %dx |
| 254 | sti | 248 | addw $512, %dx |
| 249 | jnc 1f | ||
| 250 | xorw %dx, %dx # Wraparound - whole segment available | ||
| 251 | 1: testb $CAN_USE_HEAP, loadflags | ||
| 252 | jnz 2f | ||
| 253 | |||
| 254 | # No CAN_USE_HEAP | ||
| 255 | movw %ss, %dx | ||
| 256 | cmpw %ax, %dx # %ds == %ss? | ||
| 257 | movw %sp, %dx | ||
| 258 | # If so, assume %sp is reasonably set, otherwise use | ||
| 259 | # the smallest possible stack. | ||
| 260 | jne 4f # -> Smallest possible stack... | ||
| 261 | |||
| 262 | # Make sure the stack is at least minimum size. Take a value | ||
| 263 | # of zero to mean "full segment." | ||
| 264 | 2: | ||
| 265 | andw $~3, %dx # dword align (might as well...) | ||
| 266 | jnz 3f | ||
| 267 | movw $0xfffc, %dx # Make sure we're not zero | ||
| 268 | 3: cmpw %cx, %dx | ||
| 269 | jnb 5f | ||
| 270 | 4: movw %cx, %dx # Minimum value we can possibly use | ||
| 271 | 5: movw %ax, %ss | ||
| 272 | movzwl %dx, %esp # Clear upper half of %esp | ||
| 273 | sti # Now we should have a working stack | ||
| 274 | |||
| 275 | # We will have entered with %cs = %ds+0x20, normalize %cs so | ||
| 276 | # it is on par with the other segments. | ||
| 277 | pushw %ds | ||
| 278 | pushw $6f | ||
| 279 | lretw | ||
| 280 | 6: | ||
| 255 | 281 | ||
| 256 | # Check signature at end of setup | 282 | # Check signature at end of setup |
| 257 | cmpl $0x5a5aaa55, setup_sig | 283 | cmpl $0x5a5aaa55, setup_sig |
diff --git a/arch/x86/boot/video-bios.c b/arch/x86/boot/video-bios.c index 68e65d95cdfd..ed0672a81870 100644 --- a/arch/x86/boot/video-bios.c +++ b/arch/x86/boot/video-bios.c | |||
| @@ -79,7 +79,7 @@ static int bios_probe(void) | |||
| 79 | video_bios.modes = GET_HEAP(struct mode_info, 0); | 79 | video_bios.modes = GET_HEAP(struct mode_info, 0); |
| 80 | 80 | ||
| 81 | for (mode = 0x14; mode <= 0x7f; mode++) { | 81 | for (mode = 0x14; mode <= 0x7f; mode++) { |
| 82 | if (heap_free() < sizeof(struct mode_info)) | 82 | if (!heap_free(sizeof(struct mode_info))) |
| 83 | break; | 83 | break; |
| 84 | 84 | ||
| 85 | if (mode_defined(VIDEO_FIRST_BIOS+mode)) | 85 | if (mode_defined(VIDEO_FIRST_BIOS+mode)) |
diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c index 192190710710..4716b9a96357 100644 --- a/arch/x86/boot/video-vesa.c +++ b/arch/x86/boot/video-vesa.c | |||
| @@ -57,7 +57,7 @@ static int vesa_probe(void) | |||
| 57 | while ((mode = rdfs16(mode_ptr)) != 0xffff) { | 57 | while ((mode = rdfs16(mode_ptr)) != 0xffff) { |
| 58 | mode_ptr += 2; | 58 | mode_ptr += 2; |
| 59 | 59 | ||
| 60 | if (heap_free() < sizeof(struct mode_info)) | 60 | if (!heap_free(sizeof(struct mode_info))) |
| 61 | break; /* Heap full, can't save mode info */ | 61 | break; /* Heap full, can't save mode info */ |
| 62 | 62 | ||
| 63 | if (mode & ~0x1ff) | 63 | if (mode & ~0x1ff) |
diff --git a/arch/x86/boot/video.c b/arch/x86/boot/video.c index e4ba897bf9a3..ad9712f01739 100644 --- a/arch/x86/boot/video.c +++ b/arch/x86/boot/video.c | |||
| @@ -371,7 +371,7 @@ static void save_screen(void) | |||
| 371 | saved.curx = boot_params.screen_info.orig_x; | 371 | saved.curx = boot_params.screen_info.orig_x; |
| 372 | saved.cury = boot_params.screen_info.orig_y; | 372 | saved.cury = boot_params.screen_info.orig_y; |
| 373 | 373 | ||
| 374 | if (heap_free() < saved.x*saved.y*sizeof(u16)+512) | 374 | if (!heap_free(saved.x*saved.y*sizeof(u16)+512)) |
| 375 | return; /* Not enough heap to save the screen */ | 375 | return; /* Not enough heap to save the screen */ |
| 376 | 376 | ||
| 377 | saved.data = GET_HEAP(u16, saved.x*saved.y); | 377 | saved.data = GET_HEAP(u16, saved.x*saved.y); |
