aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhpa <hpa>2004-12-08 04:29:22 +0000
committerhpa <hpa>2004-12-08 04:29:22 +0000
commit1b142b7e70d7de4f76e418bb6788a144a5c31c30 (patch)
tree940c0e5d6cd19dc1d4868c1077bd9379e0c67f76
parent6d0222e3e60a0161a82292ca8fb308039e862e04 (diff)
downloadsyslinux-1b142b7e70d7de4f76e418bb6788a144a5c31c30.tar.gz
syslinux-1b142b7e70d7de4f76e418bb6788a144a5c31c30.tar.xz
syslinux-1b142b7e70d7de4f76e418bb6788a144a5c31c30.zip
Move all 16-bit code into one assembly file so we don't have to rely
on ld working properly
-rw-r--r--memdisk/Makefile5
-rw-r--r--memdisk/e820test.c2
-rw-r--r--memdisk/init.S16189
-rw-r--r--memdisk/memdisk.h1
-rw-r--r--memdisk/memdisk16.asm (renamed from memdisk/init32.asm)142
-rw-r--r--memdisk/setup.c6
-rw-r--r--memdisk/unzip.c1
7 files changed, 138 insertions, 208 deletions
diff --git a/memdisk/Makefile b/memdisk/Makefile
index e0da72e1..bfa0ce67 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 cadd2a7f..a0eb4008 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 0a4a330e..00000000
--- 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 5377120b..b6e36f13 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
index bfbca85d..52536ae5 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 b3bcc9dd..d52e11cd 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 b7d2fdd9..18cf6e07 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)