From 1b142b7e70d7de4f76e418bb6788a144a5c31c30 Mon Sep 17 00:00:00 2001 From: hpa Date: Wed, 8 Dec 2004 04:29:22 +0000 Subject: [PATCH] Move all 16-bit code into one assembly file so we don't have to rely on ld working properly --- memdisk/Makefile | 5 +- memdisk/e820test.c | 2 +- memdisk/init.S16 | 189 ---------------------------------- memdisk/memdisk.h | 1 + memdisk/{init32.asm => memdisk16.asm} | 142 ++++++++++++++++++++++--- memdisk/setup.c | 6 +- memdisk/unzip.c | 1 + 7 files changed, 138 insertions(+), 208 deletions(-) delete mode 100644 memdisk/init.S16 rename memdisk/{init32.asm => memdisk16.asm} (81%) diff --git a/memdisk/Makefile b/memdisk/Makefile index e0da72e..bfa0ce6 100644 --- a/memdisk/Makefile +++ b/memdisk/Makefile @@ -20,12 +20,13 @@ M32 := $(call gcc_ok,-m32,) ALIGN := $(call gcc_ok,-falign-functions=0 -falign-jumps=0 -falign-loops=0,-malign-functions=0 -malign-jumps=0 -malign-loops=0) CC = gcc $(M32) -CFLAGS = -g -W -Wall -Os -fomit-frame-pointer -march=i386 $(ALIGN) \ +CFLAGS = -g -W -Wall -Wno-sign-compare \ + -Os -fomit-frame-pointer -march=i386 $(ALIGN) \ -DVERSION='"$(VERSION)"' -DDATE='"$(DATE)"' LDFLAGS = -g INCLUDE = -I../com32/include LD = ld -m elf_i386 -NASM = nasm -O99 +NASM = nasm -O99 -dVERSION='"$(VERSION)"' -dDATE='"$(DATE)"' NINCLUDE = OBJCOPY = objcopy PERL = perl diff --git a/memdisk/e820test.c b/memdisk/e820test.c index cadd2a7..a0eb400 100644 --- a/memdisk/e820test.c +++ b/memdisk/e820test.c @@ -44,7 +44,7 @@ void printranges(void) { } } -int main(int argc, char *argv[]) +int main(void) { uint64_t start, len; uint32_t type; diff --git a/memdisk/init.S16 b/memdisk/init.S16 deleted file mode 100644 index 0a4a330..0000000 --- a/memdisk/init.S16 +++ /dev/null @@ -1,189 +0,0 @@ -/* $Id$ */ -/* ----------------------------------------------------------------------- * - * - * Copyright 2001 H. Peter Anvin - All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, Inc., 53 Temple Place Ste 330, - * Bostom MA 02111-1307, USA; either version 2 of the License, or - * (at your option) any later version; incorporated herein by reference. - * - * ----------------------------------------------------------------------- */ - -/* - * init.S - * - * memdisk initialization code - * - * This module *MUST* get linked first into the image - */ - -#include "version.h" - - .text - .code16 - -/* - * The header derives directly from the Linux kernel and must be first - * in the binary, hence section .init - */ - .org 497 -setup_sects: .byte 0 # Filled in later -root_flags: .word 0 -syssize: .word 0 -swap_dev: .word 0 -ram_size: .word 0 -vid_mode: .word 0 -root_dev: .word 0 -boot_flag: .word 0xAA55 - - .globl _start -_start: - jmp start - - # This is the setup header, and it must start at %cs:2 (old 0x9020:2) - - .ascii "HdrS" # header signature - .word 0x0203 # header version number (>= 0x0105) - # or else old loadlin-1.5 will fail) -realmode_swtch: .word 0, 0 # default_switch, SETUPSEG -start_sys_seg: .word 0x1000 # obsolete -version_ptr: .word memdisk_version-0x200 - # pointing to kernel version string - -type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, - # Bootlin, SYSLX, bootsect...) - # See Documentation/i386/boot.txt for - # assigned ids - - # flags, unused bits must be zero (RFU) bit within loadflags -loadflags: -LOADED_HIGH = 1 # If set, the kernel is loaded high -CAN_USE_HEAP = 0x80 # If set, the loader also has set - # heap_end_ptr to tell how much - # space behind setup.S can be used for - # heap purposes. - # Only the loader knows what is free - - .byte LOADED_HIGH # Dont force the loader to move - # us to 0x90000 - -setup_move_size: .word 0 # Unused - -code32_start: # here loaders can put a different - # start address for 32-bit code. - .long 0x100000 # 0x100000 = default for big kernel - -ramdisk_image: .long 0 # address of loaded ramdisk image - # Here the loader puts the 32-bit - # address where it loaded the image. - # This only will be read by the kernel. - -ramdisk_size: .long 0 # its size in bytes - -bootsect_kludge: - .word 0, 0 - -heap_end_ptr: .word 0 # (Header version 0x0201 or later) - # space from here (exclusive) down to - # end of setup code can be used by setup - # for local heap purposes. - -pad1: .word 0 -cmd_line_ptr: .long 0 # (Header version 0x0202 or later) - # If nonzero, a 32-bit pointer - # to the kernel command line. - # The command line should be - # located between the start of - # setup and the end of low - # memory (0xa0000), or it may - # get overwritten before it - # gets read. If this field is - # used, there is no longer - # anything magical about the - # 0x90000 segment; the setup - # can be located anywhere in - # low memory 0x10000 or higher. - -ramdisk_max: .long 0xffffffff # Load ramdisk as high as - # absolutely possible - -/* ------------------- End of setup header --------------------------- */ - -LOWSEG = 0x0800 # 0x8000 physical - -/* - * Move ourselves down in memory to reduce the risk of conflicts; - * the canonicalize CS to match the other segments... - * - * The C code uses 32-bit registers to make sure the high part of - * %esp is zero. - * - * The C code expects %cs == %ds == %es == %ss, and %fs == 0. - */ -start: - movw $LOWSEG,%ax - movw %ax,%es - movzbw setup_sects,%cx - inc %cx # Add one for the boot sector - shlw $7,%cx # Convert to dwords - xorw %si,%si - xorw %di,%di - movw %si,%fs # %fs -> zero segment - cld - rep ; movsl %ds:(%si),%es:(%di) - movw %ax,%ds - movw %ax,%ss - xorl %esp,%esp # Stack at the top of the segment - ljmp $LOWSEG, $startc - -startc: -/* - * Copy the command line, if there is one - */ - xorw %di,%di # Bottom of our own segment - movl cmd_line_ptr, %eax - andl %eax,%eax - jz endcmd # No command line? - movw %ax,%si - shrl $4,%eax # Convert to a segment address - andw $0x000F,%si # Starting offset - movw %ax,%gs - movw $496,%cx # Maximum number of bytes -copycmd: - lodsb %gs:(%si),%al - andb %al,%al # Make sure we're null-terminated - jz endcmd - stosb %al,%es:(%di) - loopw copycmd -endcmd: - xorb %al,%al - stosb %al,%es:(%di) -/* - * Jump to 32-bit code - */ - sti - call init32 # Call the 32-bit code - # The setup function returns the drive number, - # which should be returned in %dl - movw %ax,%dx - - # If the 32-bit code returns, we are good to go, and the - # new boot sector is already loaded - cli - movw $0x7c00,%sp - xorw %si,%si # Not a partition BS - SI <- 0 - movw %si,%ds - movw %si,%es - movw %si,%fs - movw %si,%gs - movw %si,%ss - ljmp $0,$0x7c00 # Entrypoint at 0000:7C00 - - .section ".rodata","a" -memdisk_version: - .ascii "MEMDISK " VERSION " " DATE - .ascii "Copyright " FIRSTYEAR "-" COPYYEAR " H. Peter Anvin" - .byte 0 - diff --git a/memdisk/memdisk.h b/memdisk/memdisk.h index 5377120..b6e36f1 100644 --- a/memdisk/memdisk.h +++ b/memdisk/memdisk.h @@ -36,6 +36,7 @@ extern void __attribute__((noreturn)) die(void); /* Standard routines */ #define memcpy(a,b,c) __builtin_memcpy(a,b,c) #define memset(a,b,c) __builtin_memset(a,b,c) +#define strcpy(a,b) __builtin_strcpy(a,b) #define strlen(a) __builtin_strlen(a) /* memcpy() but returns a pointer to end of buffer */ diff --git a/memdisk/init32.asm b/memdisk/memdisk16.asm similarity index 81% rename from memdisk/init32.asm rename to memdisk/memdisk16.asm index bfbca85..52536ae 100644 --- a/memdisk/init32.asm +++ b/memdisk/memdisk16.asm @@ -2,7 +2,7 @@ ;; $Id$ ;; ----------------------------------------------------------------------- ;; -;; Copyright 1994-2003 H. Peter Anvin - All Rights Reserved +;; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -13,17 +13,18 @@ ;; ----------------------------------------------------------------------- ;; -;; init32.asm -;; -;; Routine to trampoline into 32-bit protected memory. This code is -;; derived from bcopy32.inc and com32.inc in the main SYSLINUX distribution. +;; init16.asm +;; +;; Routine to initialize and to trampoline into 32-bit +;; protected memory. This code is derived from bcopy32.inc and +;; com32.inc in the main SYSLINUX distribution. ;; -%define MY_CS 0x0800 -%define CS_BASE (MY_CS << 4) +MY_CS equ 0x0800 ; Segment address to use +CS_BASE equ (MY_CS << 4) ; Corresponding address ; Low memory bounce buffer -%define BOUNCE_SEG (MY_CS+0x1000) +BOUNCE_SEG equ (MY_CS+0x1000) %define DO_WBINVD 0 @@ -33,8 +34,121 @@ section .data align=16 section .bss align=16 - global init32 - +;; ----------------------------------------------------------------------- +;; Kernel image header +;; ----------------------------------------------------------------------- + + section .text ; Must be first in image + bits 16 + + times 497 db 0 ; Start of header +setup_sects db 0 +root_flags dw 0 +syssize dw 0 +swap_dev dw 0 +ram_size dw 0 +vid_mode dw 0 +root_dev dw 0 +boot_flag dw 0xAA55 + +_start: jmp short start + + db "HdrS" ; Header signature + dw 0x0203 ; Header version number + +realmode_swtch dw 0, 0 ; default_switch, SETUPSEG +start_sys_seg dw 0x1000 ; obsolete +version_ptr dw memdisk_version-0x200 ; version string ptr +type_of_loader db 0 ; Filled in by boot loader +loadflags db 1 ; Please load high +setup_move_size dw 0 ; Unused +code32_start dd 0x100000 ; 32-bit start address +ramdisk_image dd 0 ; Loaded ramdisk image address +ramdisk_size dd 0 ; Size of loaded ramdisk +bootsect_kludge dw 0, 0 +heap_end_ptr dw 0 +pad1 dw 0 +cmd_line_ptr dd 0 ; Command line +ramdisk_max dd 0xffffffff ; Highest allowed ramdisk address + + section .rodata +memdisk_version: + db "MEMDISK ", VERSION, " ", DATE, 0 + +;; ----------------------------------------------------------------------- +;; End kernel image header +;; ----------------------------------------------------------------------- + +; +; Move ourselves down into memory to reduce the risk of conflicts; +; then canonicalize CS to match the other segments. +; + section .text + bits 16 +start: + mov ax,MY_CS + mov es,ax + movzx cx,byte [setup_sects] + inc cx ; Add one for the boot sector + shl cx,7 ; Convert to dwords + xor si,si + xor di,di + mov fs,si ; fs <- 0 + cld + rep movsd + mov ds,ax + mov ss,ax + xor esp,esp ; Stack at top of 64K segment + jmp MY_CS:.next +.next: + +; +; Copy the command line, if there is one +; +copy_cmdline: + xor di,di ; Bottom of our own segment (= "boot sector") + mov eax,[cmd_line_ptr] + and eax,eax + jz .endcmd ; No command line + mov si,ax + shr eax,4 ; Convert to segment + and si,0x000F ; Starting offset only + mov gs,ax + mov cx,496 ; Max number of bytes +.copycmd: + lodsb + and al,al + jz .endcmd + stosb + loop .copycmd +.endcmd: + xor al,al + stosb + +; +; Now jump to 32-bit code +; + sti + call init32 +; +; When init32 returns, we have been set up, the new boot sector loaded, +; and we should go and and run the newly loaded boot sector +; +; The setup function returns (in AL) the drive number which should be +; put into DL +; + mov dx,ax + + cli + xor esi,esi ; No partition table involved + mov ds,si ; Make all the segments consistent + mov es,si + mov fs,si + mov gs,si + mov ss,si + mov esp,0x7C00 ; Good place for SP to start out + jmp 0:0x7C00 + ; ; We enter protected mode, set up a flat 32-bit environment, run rep movsd ; and then exit. IMPORTANT: This code assumes cs == MY_CS. @@ -51,7 +165,7 @@ dd (%1 & 0xff000000) | (%2 & 0xf0000) | ((%3 & 0xf0ff) << 8) | ((%1 & 0x00ff0000) >> 16) %endmacro - align 4 + align 8, db 0 call32_gdt: dw call32_gdt_size-1 ; Null descriptor - contains GDT .adj1: dd call32_gdt+CS_BASE ; pointer for LGDT instruction dw 0 @@ -75,7 +189,6 @@ call32_gdt_size: equ $-call32_gdt err_a20: db 'ERROR: A20 gate not responding!',13,10,0 - bits 16 section .bss alignb 4 SavedSSSP resd 1 ; Place to save SS:SP @@ -91,6 +204,7 @@ Target_Seg dw 20h ; Target CS A20Type dw 0 ; Default = unknown section .text + bits 16 ; ; Routines to enable and disable (yuck) A20. These routines are gathered ; from tips from a couple of sources, including the Linux kernel and @@ -110,7 +224,7 @@ A20Type dw 0 ; Default = unknown %define A20_KBC 3 ; A20 through KBC %define A20_FAST 4 ; A20 through port 92h - align 2 + align 2, db 0 A20List dw a20_dunno, a20_none, a20_bios, a20_kbc, a20_fast A20DList dw a20d_dunno, a20d_none, a20d_bios, a20d_kbc, a20d_fast a20_adjust_cnt equ ($-A20List)/2 @@ -360,7 +474,7 @@ try_wbinvd: alignb 4 PMESP resd 1 ; Protected mode %esp - section .idt nobits alloc exec write align=4096 + section .idt nobits align=4096 alignb 4096 pm_idt resb 4096 ; Protected-mode IDT, followed by interrupt stubs diff --git a/memdisk/setup.c b/memdisk/setup.c index b3bcc9d..d52e11c 100644 --- a/memdisk/setup.c +++ b/memdisk/setup.c @@ -17,7 +17,6 @@ #include "version.h" #include "memdisk.h" -/* A pointer to this is stored in the header */ const char memdisk_version[] = "MEMDISK " VERSION " " DATE; const char copyright[] = @@ -369,6 +368,8 @@ struct dosemu_header { uint8_t pad[105]; } __attribute__((packed)); +#define FOUR(a,b,c,d) (((a) << 24)|((b) << 16)|((c) << 8)|(d)) + const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size) { static struct geometry hd_geometry = { 0, 0, 0, 0, 0, 0, 0x80 }; @@ -400,7 +401,8 @@ const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size) /* Do we have a DOSEMU header? */ memcpy(&dosemu, (char *)where+hd_geometry.offset, sizeof dosemu); - if ( !__builtin_memcmp("DOSEMU", dosemu.magic, 7) ) { + if ( ((unsigned long *)dosemu.magic)[0] == FOUR('D','O','S','E') && + (((unsigned long *)dosemu.magic)[1] & 0xffffff) == FOUR('M','U',0,0) ) { /* Always a hard disk unless overruled by command-line options */ hd_geometry.driveno = 0x80; hd_geometry.type = 0; diff --git a/memdisk/unzip.c b/memdisk/unzip.c index b7d2fdd..18cf6e0 100644 --- a/memdisk/unzip.c +++ b/memdisk/unzip.c @@ -122,6 +122,7 @@ static void *malloc(int size) static void free(void *where) { /* Don't care */ + (void)where; } static void gzip_mark(void **ptr) -- 2.7.4