summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-06-09 10:49:50 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-06-09 10:49:50 -0700
commitab42c9f0237af9f116433478268587e847f2eb44 (patch)
tree1bc66e000c40a8d579ccdda9b736d47358ec4c20
parentd19a7c6a6989f19c4f82212a9a7b654bdf289739 (diff)
parent78edf2be58fd9106af088b8a2b09fca1d41e1dfa (diff)
downloadsyslinux-ab42c9f0237af9f116433478268587e847f2eb44.tar.gz
Merge branch 'master' into core32
-rw-r--r--NEWS3
-rw-r--r--com32/menu/menumain.c5
-rw-r--r--core/diskstart.inc8
-rw-r--r--core/extlinux.asm4
-rw-r--r--core/pxelinux.asm34
-rw-r--r--memdisk/Makefile4
-rw-r--r--memdisk/conio.c41
-rw-r--r--memdisk/conio.h2
-rw-r--r--memdisk/memdisk.h74
-rw-r--r--memdisk/memdisk16.asm237
-rw-r--r--memdisk/memmove.S139
-rw-r--r--memdisk/msetup.c11
-rw-r--r--memdisk/setup.c216
-rw-r--r--memdisk/start32.S74
-rw-r--r--memdisk/unzip.c14
15 files changed, 600 insertions, 266 deletions
diff --git a/NEWS b/NEWS
index 70563f72..5a18525b 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,9 @@ Changes in 3.82:
* ISOLINUX: deal with systems which return from INT 13h with
interrupts disabled.
* Do not invoke the idle handler during large file loads.
+ * Simple menu: make ONTIMEOUT work with MENU HIDDEN.
+ * PXELINUX: handle TFTP servers which have extra NULs at the
+ end of an OACK packet.
Changes in 3.81:
* Shuffler: fix bug in real-mode entry. This affected a
diff --git a/com32/menu/menumain.c b/com32/menu/menumain.c
index b86e9b4d..82f0018c 100644
--- a/com32/menu/menumain.c
+++ b/com32/menu/menumain.c
@@ -724,7 +724,10 @@ static const char *do_hidden_menu(void)
}
}
- return cm->menu_entries[cm->defentry]->cmdline; /* Default entry */
+ if (cm->ontimeout)
+ return cm->ontimeout;
+ else
+ return cm->menu_entries[cm->defentry]->cmdline; /* Default entry */
}
static const char *run_menu(void)
diff --git a/core/diskstart.inc b/core/diskstart.inc
index b8047264..d7279028 100644
--- a/core/diskstart.inc
+++ b/core/diskstart.inc
@@ -501,6 +501,7 @@ ldlinux_ent:
;
jmp 0:.next
.next:
+ sti ; In case of broken INT 13h BIOSes
;
; Tell the user we got this far
@@ -629,11 +630,16 @@ writestr_early:
ret
+;
; getlinsecsr: save registers, call getlinsec, restore registers
+; Save/restore the flags, too, especially IF.
;
-getlinsecsr: pushad
+getlinsecsr:
+ pushfd
+ pushad
call getlinsec
popad
+ popfd
ret
;
diff --git a/core/extlinux.asm b/core/extlinux.asm
index 3a054b22..20ba9c6a 100644
--- a/core/extlinux.asm
+++ b/core/extlinux.asm
@@ -121,7 +121,7 @@ Files resb MAX_OPEN*open_file_t_size
mov bx,SuperBlock
mov eax,1024 >> SECTOR_SHIFT
mov bp,ax
- call getlinsec
+ call getlinsecsr
;
; Compute some values...
@@ -212,7 +212,7 @@ getonesec_ext:
getlinsec_ext:
cmp eax,[SecPerClust]
- jae getlinsec ; Nothing fancy
+ jae getlinsecsr ; Nothing fancy
; If we get here, at least part of what we want is in the
; zero block. Zero one sector at a time and loop.
diff --git a/core/pxelinux.asm b/core/pxelinux.asm
index b866369c..3f7cb8c6 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -1114,7 +1114,17 @@ searchdir:
; SI -> first byte of options; [E]CX -> byte count
.parse_oack:
jcxz .done_pkt ; No options acked
+
.get_opt_name:
+ ; If we find an option which starts with a NUL byte,
+ ; (a null option), we're either seeing garbage that some
+ ; TFTP servers add to the end of the packet, or we have
+ ; no clue how to parse the rest of the packet (what is
+ ; an option name and what is a value?) In either case,
+ ; discard the rest.
+ cmp byte [si],0
+ je .done_pkt
+
mov di,si
mov bx,si
.opt_name_loop: lodsb
@@ -1124,10 +1134,10 @@ searchdir:
stosb
loop .opt_name_loop
; We ran out, and no final null
- jmp .err_reply
+ jmp .done_pkt ; Ignore runt option
.got_opt_name: ; si -> option value
dec cx ; bytes left in pkt
- jz .err_reply ; Option w/o value
+ jz .done_pkt ; Option w/o value, ignore
; Parse option pointed to by bx; guaranteed to be
; null-terminated.
@@ -1150,7 +1160,8 @@ searchdir:
pop si
pop cx
- jmp .err_reply ; Non-negotiated option returned
+ ; Non-negotiated option returned, no idea what it means...
+ jmp .err_reply
.get_value: pop si ; si -> option value
pop cx ; cx -> bytes left in pkt
@@ -1230,13 +1241,13 @@ searchdir:
pop es
jmp .done_pkt
-.err_reply: ; Option negotiation error. Send ERROR reply.
+.err_reply: ; TFTP protocol error. Send ERROR reply.
; ServerIP and gateway are already programmed in
mov si,[bp-6]
mov ax,[si+tftp_remoteport]
mov word [pxe_udp_write_pkt.rport],ax
- mov word [pxe_udp_write_pkt.buffer],tftp_opt_err
- mov word [pxe_udp_write_pkt.buffersize],tftp_opt_err_len
+ mov word [pxe_udp_write_pkt.buffer],tftp_proto_err
+ mov word [pxe_udp_write_pkt.buffersize],tftp_proto_err_len
mov di,pxe_udp_write_pkt
mov bx,PXENV_UDP_WRITE
call pxenv
@@ -2727,12 +2738,13 @@ tftp_opt_table:
tftp_opts equ ($-tftp_opt_table)/6
;
-; Error packet to return on options negotiation error
+; Error packet to return on TFTP protocol error
+; Most of our errors are OACK parsing errors, so use that error code
;
-tftp_opt_err dw TFTP_ERROR ; ERROR packet
- dw TFTP_EOPTNEG ; ERROR 8: bad options
- db 'tsize option required', 0 ; Error message
-tftp_opt_err_len equ ($-tftp_opt_err)
+tftp_proto_err dw TFTP_ERROR ; ERROR packet
+ dw TFTP_EOPTNEG ; ERROR 8: OACK error
+ db 'TFTP protocol error', 0 ; Error message
+tftp_proto_err_len equ ($-tftp_proto_err)
alignz 4
ack_packet_buf: dw TFTP_ACK, 0 ; TFTP ACK packet
diff --git a/memdisk/Makefile b/memdisk/Makefile
index 3bb97ffd..e1a89351 100644
--- a/memdisk/Makefile
+++ b/memdisk/Makefile
@@ -38,10 +38,10 @@ endif
# Important: init.o16 must be first!!
OBJS16 = init.o16 init32.o
OBJS32 = start32.o setup.o msetup.o e820func.o conio.o memcpy.o memset.o \
- unzip.o memdisk_chs.o memdisk_edd.o
+ memmove.o unzip.o memdisk_chs.o memdisk_edd.o
CSRC = setup.c msetup.c e820func.c conio.c unzip.c
-SSRC = start32.S memcpy.S memset.S
+SSRC = start32.S memcpy.S memset.S memmove.S
NASMSRC = memdisk_chs.asm memdisk_edd.asm memdisk16.asm
all: memdisk # e820test
diff --git a/memdisk/conio.c b/memdisk/conio.c
index 9ccc8e2d..d1f0862c 100644
--- a/memdisk/conio.c
+++ b/memdisk/conio.c
@@ -30,7 +30,7 @@ int putchar(int ch)
}
regs.eax.w[0] = 0x0e00 | (ch & 0xff);
- syscall(0x10, &regs, NULL);
+ intcall(0x10, &regs, NULL);
return ch;
}
@@ -109,11 +109,11 @@ static char *number(char *str, long num, int base, int size, int precision,
int type)
{
char c, sign, tmp[66];
- const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+ const char *digits = "0123456789abcdef";
int i;
if (type & LARGE)
- digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ digits = "0123456789ABCDEF";
if (type & LEFT)
type &= ~ZEROPAD;
if (base < 2 || base > 36)
@@ -173,9 +173,6 @@ static char *number(char *str, long num, int base, int size, int precision,
return str;
}
-/* Forward decl. needed for IP address printing stuff... */
-int sprintf(char *buf, const char *fmt, ...);
-
int vsprintf(char *buf, const char *fmt, va_list args)
{
int len;
@@ -346,6 +343,7 @@ repeat:
return str - buf;
}
+#if 0
int sprintf(char *buf, const char *fmt, ...)
{
va_list args;
@@ -356,18 +354,41 @@ int sprintf(char *buf, const char *fmt, ...)
va_end(args);
return i;
}
+#endif
+
+int vprintf(const char *fmt, va_list args)
+{
+ char printf_buf[2048];
+ int printed;
+
+ printed = vsprintf(printf_buf, fmt, args);
+ puts(printf_buf);
+ return printed;
+}
int printf(const char *fmt, ...)
{
- char printf_buf[1024];
va_list args;
int printed;
va_start(args, fmt);
- printed = vsprintf(printf_buf, fmt, args);
+ printed = vprintf(fmt, args);
va_end(args);
+ return printed;
+}
- puts(printf_buf);
+/*
+ * Jump here if all hope is gone...
+ */
+void __attribute__ ((noreturn)) die(const char *fmt, ...)
+{
+ va_list ap;
- return printed;
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+
+ sti();
+ for (;;)
+ asm volatile("hlt");
}
diff --git a/memdisk/conio.h b/memdisk/conio.h
index 9fa89919..9775e62a 100644
--- a/memdisk/conio.h
+++ b/memdisk/conio.h
@@ -25,7 +25,9 @@
int putchar(int);
int puts(const char *);
+int vprintf(const char *, va_list ap);
int printf(const char *, ...);
+void __attribute__((noreturn)) die(const char *, ...);
unsigned int atou(const char *);
#endif
diff --git a/memdisk/memdisk.h b/memdisk/memdisk.h
index 1ab2c000..b6b277a8 100644
--- a/memdisk/memdisk.h
+++ b/memdisk/memdisk.h
@@ -24,21 +24,63 @@
/* We use the com32 interface for calling 16-bit code */
#include <com32.h>
-/* The real-mode segment */
-#define LOW_SEG 0x0800
-
#define __cdecl __attribute__((cdecl,regparm(0)))
-typedef void (*syscall_t) (uint8_t, com32sys_t *, com32sys_t *);
-extern __cdecl syscall_t syscall;
-extern void *sys_bounce;
-
-/* What to call when we're dead */
-extern void __attribute__ ((noreturn)) die(void);
+void __cdecl intcall(uint8_t, com32sys_t *, com32sys_t *);
+
+/* Structure passed in from the real-mode code */
+struct real_mode_args {
+ uint32_t rm_return;
+ uint32_t rm_intcall;
+ uint32_t rm_bounce;
+ uint32_t rm_base;
+ uint32_t rm_handle_interrupt;
+ uint32_t rm_gdt;
+ uint32_t rm_size;
+ uint32_t rm_pmjmp;
+ uint32_t rm_rmjmp;
+};
+extern struct real_mode_args rm_args;
+#define sys_bounce ((void *)rm_args.rm_bounce)
+
+/* This is the header in the boot sector/setup area */
+struct setup_header {
+ char cmdline[0x1f1];
+ uint8_t setup_secs;
+ uint16_t syssize;
+ uint16_t swap_dev;
+ uint16_t ram_size;
+ uint16_t vid_mode;
+ uint16_t root_dev;
+ uint16_t boot_flag;
+ uint16_t jump;
+ char header[4];
+ uint16_t version;
+ uint32_t realmode_swtch;
+ uint32_t start_sys;
+ uint8_t type_of_loader;
+ uint8_t loadflags;
+ uint16_t setup_move_size;
+ uint32_t code32_start;
+ uint32_t ramdisk_image;
+ uint32_t ramdisk_size;
+ uint32_t bootsect_kludge;
+ uint16_t head_end_ptr;
+ uint16_t pad1;
+ uint32_t cmd_line_ptr;
+ uint32_t initrd_addr_max;
+ uint32_t esdi;
+ uint32_t edx;
+ uint32_t sssp;
+ uint32_t csip;
+};
+#define shdr ((struct setup_header *)rm_args.rm_base)
/* Standard routines */
-#define memcpy(a,b,c) __builtin_memcpy(a,b,c)
-#define memset(a,b,c) __builtin_memset(a,b,c)
+void *memcpy(void *, const void *, size_t);
+void *memset(void *, int, size_t);
+void *memmove(void *, const void *, size_t);
+
#define strcpy(a,b) __builtin_strcpy(a,b)
static inline size_t strlen(const char *__a)
@@ -75,6 +117,16 @@ static inline int memcmp(const void *__a, const void *__b, unsigned int __n)
return 0;
}
+static inline void sti(void)
+{
+ asm volatile("sti");
+}
+
+static inline void cli(void)
+{
+ asm volatile("cli");
+}
+
/* Decompression */
extern int check_zip(void *indata, uint32_t size, uint32_t * zbytes_p,
uint32_t * dbytes_p, uint32_t * orig_crc,
diff --git a/memdisk/memdisk16.asm b/memdisk/memdisk16.asm
index d43404e8..0c5b9973 100644
--- a/memdisk/memdisk16.asm
+++ b/memdisk/memdisk16.asm
@@ -2,6 +2,7 @@
;; -----------------------------------------------------------------------
;;
;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
+;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
;;
;; 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
@@ -29,11 +30,12 @@ BOUNCE_SEG equ (MY_CS+0x1000)
%define DO_WBINVD 0
-%define STACK_HEAP_SIZE (128*1024)
-
section .rodata align=16
section .data align=16
section .bss align=16
+ section .stack align=16 nobits
+stack resb 512
+stack_end equ $
;; -----------------------------------------------------------------------
;; Kernel image header
@@ -78,6 +80,8 @@ ramdisk_max dd 0xffffffff ; Highest allowed ramdisk address
;
b_esdi dd 0 ; ES:DI for boot sector invocation
b_edx dd 0 ; EDX for boot sector invocation
+b_sssp dd 0 ; SS:SP on boot sector invocation
+b_csip dd 0 ; CS:IP on boot sector invocation
section .rodata
memdisk_version:
@@ -106,7 +110,7 @@ start:
rep movsd
mov ds,ax
mov ss,ax
- xor esp,esp ; Stack at top of 64K segment
+ mov esp,stack_end
jmp MY_CS:.next
.next:
@@ -153,9 +157,9 @@ copy_cmdline:
mov ds,si ; Make all the segments consistent
mov fs,si
mov gs,si
- mov ss,si
- mov esp,0x7C00 ; Good place for SP to start out
- call 0:0x7C00
+ lss sp,[cs:b_sssp]
+ movzx esp,sp
+ call far [cs:b_csip]
int 18h ; A far return -> INT 18h
;
@@ -166,7 +170,9 @@ copy_cmdline:
; segments, but this stuff is painful enough as it is without having to rely
; on everything happening "as it ought to."
;
- section .rodata
+DummyTSS equ 0x580 ; Hopefully safe place in low mmoery
+
+ section .data
; desc base, limit, flags
%macro desc 3
@@ -179,15 +185,16 @@ call32_gdt: dw call32_gdt_size-1 ; Null descriptor - contains GDT
.adj1: dd call32_gdt+CS_BASE ; pointer for LGDT instruction
dw 0
- ; 0008: Code segment, use16, readable, dpl 0, base CS_BASE, 64K
+ ; 0008: Dummy TSS to make Intel VT happy
+ ; Should never be actually accessed...
+ desc DummyTSS, 103, 0x8089
+
+ ; 0010: Code segment, use16, readable, dpl 0, base CS_BASE, 64K
desc CS_BASE, 0xffff, 0x009b
- ; 0010: Data segment, use16, read/write, dpl 0, base CS_BASE, 64K
+ ; 0018: Data segment, use16, read/write, dpl 0, base CS_BASE, 64K
desc CS_BASE, 0xffff, 0x0093
- ; 0018: Data segment, use16, read/write, dpl 0, base 0, 4G
- desc 0, 0xfffff, 0x809b
-
; 0020: Code segment, use32, read/write, dpl 0, base 0, 4G
desc 0, 0xfffff, 0xc09b
@@ -200,13 +207,12 @@ err_a20: db 'ERROR: A20 gate not responding!',13,10,0
section .bss
alignb 4
-SavedSSSP resd 1 ; Place to save SS:SP
Return resd 1 ; Return value
-A20Test resw 1 ; Space to test A20
+SavedSP resw 1 ; Place to save SP
A20Tries resb 1
section .data
- alignb 4
+ align 4, db 0
Target dd 0 ; Target address
Target_Seg dw 20h ; Target CS
@@ -381,22 +387,38 @@ a20_done: popad
; This routine tests if A20 is enabled (ZF = 0). This routine
; must not destroy any register contents.
;
+
+; This is the INT 1Fh vector, which is standard PCs is used by the
+; BIOS when the screen is in graphics mode. Even if it is, it points to
+; data, not code, so it should be safe enough to fiddle with.
+A20Test equ (1Fh*4)
+
a20_test:
+ push ds
push es
push cx
- push ax
- mov cx,0FFFFh ; HMA = segment 0FFFFh
- mov es,cx
+ push eax
+ xor ax,ax
+ mov ds,ax ; DS == 0
+ dec ax
+ mov es,ax ; ES == 0FFFFh
mov cx,32 ; Loop count
- mov ax,[A20Test]
-.a20_wait: inc ax
- mov [A20Test],ax
- io_delay ; Serialize, and fix delay
- cmp ax,[es:A20Test+CS_BASE+10h]
+ mov eax,[A20Test]
+ cmp eax,[es:A20Test+10h]
+ jne .a20_done
+ push eax
+.a20_wait:
+ inc eax
+ mov [A20Test],eax
+ io_delay
+ cmp eax,[es:A20Test+10h]
loopz .a20_wait
-.a20_done: pop ax
+ pop dword [A20Test] ; Restore original value
+.a20_done:
+ pop eax
pop cx
pop es
+ pop ds
ret
disable_a20:
@@ -507,53 +529,65 @@ pm_idt resb 4096 ; Protected-mode IDT, followed by interrupt stubs
pm_entry: equ 0x100000
section .rodata
- align 4, db 0
-call32_pmidt:
- dw 8*256 ; Limit
- dd pm_idt+CS_BASE ; Address
-
+ align 2, db 0
call32_rmidt:
dw 0ffffh ; Limit
dd 0 ; Address
+ section .data
+ alignb 2
+call32_pmidt:
+ dw 8*256 ; Limit
+ dd 0 ; Address (entered later)
+
section .text
;
; This is the main entrypoint in this function
;
init32:
- mov ebx,call32_call_start+CS_BASE ; Where to go in PM
+ mov bx,call32_call_start ; Where to go in PM
+;
+; Enter protected mode. BX contains the entry point relative to the
+; real-mode CS.
+;
call32_enter_pm:
mov ax,cs
mov ds,ax
+ movzx ebp,ax
+ shl ebp,4 ; EBP <- CS_BASE
+ movzx ebx,bx
+ add ebx,ebp ; entry point += CS_BASE
cli
- mov [SavedSSSP],sp
- mov [SavedSSSP+2],ss
+ mov [SavedSP],sp
cld
- call a20_test
- jnz .a20ok
call enable_a20
-
-.a20ok:
- lgdt [call32_gdt] ; Set up GDT
- lidt [call32_pmidt] ; Set up the IDT
+ mov byte [call32_gdt+8+5],89h ; Mark TSS unbusy
+ o32 lgdt [call32_gdt] ; Set up GDT
+ o32 lidt [call32_pmidt] ; Set up IDT
mov eax,cr0
or al,1
mov cr0,eax ; Enter protected mode
- jmp 20h:dword .in_pm+CS_BASE
+ jmp 20h:strict dword .in_pm+CS_BASE
+.pm_jmp equ $-6
+
bits 32
.in_pm:
xor eax,eax ; Available for future use...
mov fs,eax
mov gs,eax
+ lldt ax
mov al,28h ; Set up data segments
mov es,eax
mov ds,eax
mov ss,eax
- mov esp,[PMESP+CS_BASE] ; Load protmode %esp if available
+ mov al,08h
+ ltr ax
+
+ mov esp,[ebp+PMESP] ; Load protmode %esp if available
jmp ebx ; Go to where we need to go
;
@@ -561,66 +595,22 @@ call32_enter_pm:
;
call32_call_start:
;
- ; Point the stack into low memory
- ; We have: this segment, bounce buffer, then stack+heap
- ;
- mov esp, CS_BASE + 0x20000 + STACK_HEAP_SIZE
- and esp, ~0xf
-
- ;
- ; Set up the protmode IDT and the interrupt jump buffers
- ;
- mov edi,pm_idt+CS_BASE
-
- ; Form an interrupt gate descriptor
- ; WARNING: This is broken if pm_idt crosses a 64K boundary;
- ; however, it can't because of the alignment constraints.
- mov ebx,pm_idt+CS_BASE+8*256
- mov eax,0x0020ee00
- xchg ax,bx
- xor ecx,ecx
- inc ch ; ecx <- 256
-
- push ecx
-.make_idt:
- stosd
- add eax,8
- xchg eax,ebx
- stosd
- xchg eax,ebx
- loop .make_idt
-
- pop ecx
-
- ; Each entry in the interrupt jump buffer contains
- ; the following instructions:
+ ; Set up a temporary stack in the bounce buffer;
+ ; start32.S will override this to point us to the real
+ ; high-memory stack.
;
- ; 00000000 60 pushad
- ; 00000001 B0xx mov al,<interrupt#>
- ; 00000003 E9xxxxxxxx jmp call32_handle_interrupt
-
- mov eax,0xe900b060
- mov ebx,call32_handle_interrupt+CS_BASE
- sub ebx,edi
-
-.make_ijb:
- stosd
- sub [edi-2],cl ; Interrupt #
- xchg eax,ebx
- sub eax,8
- stosd
- xchg eax,ebx
- loop .make_ijb
-
- ; Now everything is set up for interrupts...
-
+ mov esp, (BOUNCE_SEG << 4) + 0x10000
+
+ push dword call32_enter_rm.rm_jmp+CS_BASE
+ push dword call32_enter_pm.pm_jmp+CS_BASE
+ push dword stack_end ; RM size
+ push dword call32_gdt+CS_BASE
+ push dword call32_handle_interrupt+CS_BASE
+ push dword CS_BASE ; Segment base
push dword (BOUNCE_SEG << 4) ; Bounce buffer address
push dword call32_syscall+CS_BASE ; Syscall entry point
- sti ; Interrupts OK now
- call pm_entry-CS_BASE ; Run the program...
- ; ... on return ...
- mov [Return+CS_BASE],eax
+ call pm_entry-CS_BASE ; Run the program...
; ... fall through to call32_exit ...
@@ -628,15 +618,24 @@ call32_exit:
mov bx,call32_done ; Return to command loop
call32_enter_rm:
+ ; Careful here... the PM code may have relocated the
+ ; entire RM code, so we need to figure out exactly
+ ; where we are executing from. If the PM code has
+ ; relocated us, it *will* have adjusted the GDT to
+ ; match, though.
+ call .here
+.here: pop ebp
+ sub ebp,.here
+ o32 sidt [ebp+call32_pmidt]
cli
cld
- mov [PMESP+CS_BASE],esp ; Save exit %esp
+ mov [ebp+PMESP],esp ; Save exit %esp
xor esp,esp ; Make sure the high bits are zero
- jmp 08h:.in_pm16 ; Return to 16-bit mode first
+ jmp 10h:.in_pm16 ; Return to 16-bit mode first
bits 16
.in_pm16:
- mov ax,10h ; Real-mode-like segment
+ mov ax,18h ; Real-mode-like segment
mov es,ax
mov ds,ax
mov ss,ax
@@ -648,20 +647,21 @@ call32_enter_rm:
and al,~1
mov cr0,eax
jmp MY_CS:.in_rm
+.rm_jmp equ $-2
.in_rm: ; Back in real mode
- mov ax,cs ; Set up sane segments
+ mov ax,cs
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
- lss sp,[SavedSSSP] ; Restore stack
+ mov ss,ax
+ mov sp,[SavedSP] ; Restore stack
jmp bx ; Go to whereever we need to go...
call32_done:
call disable_a20
sti
- mov ax,[Return]
ret
;
@@ -679,7 +679,7 @@ call32_int_rm:
push dword edx ; Segment:offset of IVT entry
retf ; Invoke IVT routine
.cont: ; ... on resume ...
- mov ebx,call32_int_resume+CS_BASE
+ mov bx,call32_int_resume
jmp call32_enter_pm ; Go back to PM
;
@@ -700,7 +700,7 @@ call32_sys_rm:
push es
push fs
push gs
- mov ebx,call32_sys_resume+CS_BASE
+ mov bx,call32_sys_resume
jmp call32_enter_pm
;
@@ -741,13 +741,14 @@ call32_syscall:
pushfd ; Save IF among other things...
pushad ; We only need to save some, but...
cld
+ call .here
+.here: pop ebp
+ sub ebp,.here
- movzx edi,word [SavedSSSP+CS_BASE]
- movzx eax,word [SavedSSSP+CS_BASE+2]
+ movzx edi,word [ebp+SavedSP]
sub edi,54 ; Allocate 54 bytes
- mov [SavedSSSP+CS_BASE],di
- shl eax,4
- add edi,eax ; Create linear address
+ mov [ebp+SavedSP],di
+ add edi,ebp ; Create linear address
mov esi,[esp+11*4] ; Source regs
xor ecx,ecx
@@ -759,8 +760,11 @@ call32_syscall:
; encoding smaller
mov eax,[ecx+eax*4] ; Get IVT entry
stosd ; Save in stack frame
- mov eax,call32_sys_rm.return + (MY_CS << 16) ; Return seg:offs
- stosd ; Save in stack frame
+ mov ax,call32_sys_rm.return ; Return offset
+ stosw ; Save in stack frame
+ mov eax,ebp
+ shr eax,4 ; Return segment
+ stosw ; Save in stack frame
mov eax,[edi-12] ; Return flags
and eax,0x200cd7 ; Mask (potentially) unsafe flags
mov [edi-12],eax ; Primary flags entry
@@ -770,13 +774,12 @@ call32_syscall:
jmp call32_enter_rm ; Go to real mode
; On return, the 44-byte return structure is on the
- ; real-mode stack.
+ ; real-mode stack. call32_enter_pm will leave ebp
+ ; pointing to the real-mode base.
call32_sys_resume:
- movzx esi,word [SavedSSSP+CS_BASE]
- movzx eax,word [SavedSSSP+CS_BASE+2]
+ movzx esi,word [ebp+SavedSP]
mov edi,[esp+12*4] ; Dest regs
- shl eax,4
- add esi,eax ; Create linear address
+ add esi,ebp ; Create linear address
and edi,edi ; NULL pointer?
jnz .do_copy
.no_copy: mov edi,esi ; Do a dummy copy-to-self
@@ -784,7 +787,7 @@ call32_sys_resume:
mov cl,11 ; 44 bytes
rep movsd ; Copy register block
- add dword [SavedSSSP+CS_BASE],44 ; Remove from stack
+ add word [ebp+SavedSP],44 ; Remove from stack
popad
popfd
diff --git a/memdisk/memmove.S b/memdisk/memmove.S
new file mode 100644
index 00000000..b7ac6767
--- /dev/null
+++ b/memdisk/memmove.S
@@ -0,0 +1,139 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * memmove.S
+ *
+ * Reasonably efficient memmove, using aligned transfers at least
+ * for the destination operand.
+ */
+
+ .globl memmove
+ .type memmove,@function
+ .text
+memmove:
+ jecxz 3f
+
+ pushl %esi
+ pushl %edi
+ pushl %eax /* Return value */
+
+ movl %eax,%edi
+ movl %edx,%esi
+
+ cmpl %edi,%esi
+ jb 1f
+
+ /* source >= dest, forwards move */
+
+ /* Initial alignment */
+ movl %edi,%edx
+ shrl $1,%edx
+ jnc 11f
+ movsb
+ decl %ecx
+11:
+ movb %cl,%al
+ cmpl $2,%ecx
+ jb 13f
+
+ shrl $1,%edx
+ jnc 12f
+ movsw
+ subl $2,%ecx
+12:
+ /* Bulk transfer */
+ movb %cl,%al
+ shrl $2,%ecx
+ rep; movsl
+
+ /* Final alignment */
+ testb $2,%al
+ jz 14f
+ movsw
+13:
+14:
+ testb $1,%al
+ jz 15f
+ movsb
+15:
+ jmp 2f
+
+
+1:
+ /* source < dest, backwards move */
+ std
+ leal -1(%ecx,%esi),%esi
+ leal -1(%ecx,%edi),%edi
+
+ /* Initial alignment */
+ movl %edi,%edx
+ shrl $1,%edx
+ jc 21f
+ movsb
+ decl %ecx
+21:
+ decl %esi
+ decl %edi
+ movb %cl,%al
+ cmpl $2,%ecx
+ jb 23f
+ shrl $1,%edx
+ jc 22f
+ movsw
+ subl $2,%ecx
+22:
+ /* Bulk transfer */
+ subl $2,%esi
+ subl $2,%edi
+ movb %cl,%al
+ shrl $2,%ecx
+ rep; movsl
+
+ /* Final alignment */
+ addl $2,%esi
+ addl $2,%edi
+ testb $2,%al
+ jz 24f
+ movsw
+23:
+24:
+ incl %esi
+ incl %edi
+ testb $1,%al
+ jz 25f
+ movsb
+25:
+ cld
+2:
+ popl %eax /* Return value */
+ popl %edi
+ popl %esi
+3:
+ ret
+
+ .size memmove, .-memmove
diff --git a/memdisk/msetup.c b/memdisk/msetup.c
index adb35f90..f40a2c66 100644
--- a/memdisk/msetup.c
+++ b/memdisk/msetup.c
@@ -53,7 +53,7 @@ static inline int get_e820(void)
regs.edi.w[0] = OFFS(buf);
regs.es = SEG(buf);
- syscall(0x15, &regs, &regs);
+ intcall(0x15, &regs, &regs);
copied = (regs.eflags.l & 1) ? 0 : regs.ecx.l;
if (regs.eax.l != 0x534d4150 || copied < 20)
@@ -76,7 +76,7 @@ static inline void get_dos_mem(void)
com32sys_t regs;
memset(&regs, 0, sizeof regs);
- syscall(0x12, &regs, &regs);
+ intcall(0x12, &regs, &regs);
insertrange(0, (uint64_t) ((uint32_t) regs.eax.w[0] << 10), 1);
printf(" DOS: %d K\n", regs.eax.w[0]);
}
@@ -89,7 +89,7 @@ static inline int get_e801(void)
memset(&regs, 0, sizeof regs);
regs.eax.w[0] = 0xe801;
- syscall(0x15, &regs, &regs);
+ intcall(0x15, &regs, &regs);
if (!(err = regs.eflags.l & 1)) {
if (regs.eax.w[0]) {
@@ -115,7 +115,7 @@ static inline int get_88(void)
memset(&regs, 0, sizeof regs);
regs.eax.b[1] = 0x88;
- syscall(0x15, &regs, &regs);
+ intcall(0x15, &regs, &regs);
if (!(err = regs.eflags.l & 1)) {
if (regs.eax.w[0]) {
@@ -135,8 +135,7 @@ void get_mem(void)
get_dos_mem();
if (get_e801()) {
if (get_88()) {
- puts("MEMDISK: Unable to obtain memory map\n");
- die();
+ die("MEMDISK: Unable to obtain memory map\n");
}
}
}
diff --git a/memdisk/setup.c b/memdisk/setup.c
index 7e0ebc93..98c4b69d 100644
--- a/memdisk/setup.c
+++ b/memdisk/setup.c
@@ -123,38 +123,6 @@ struct patch_area {
struct edd_dpt edd_dpt;
};
-/* This is the header in the boot sector/setup area */
-struct setup_header {
- char cmdline[0x1f1];
- uint8_t setup_secs;
- uint16_t syssize;
- uint16_t swap_dev;
- uint16_t ram_size;
- uint16_t vid_mode;
- uint16_t root_dev;
- uint16_t boot_flag;
- uint16_t jump;
- char header[4];
- uint16_t version;
- uint32_t realmode_swtch;
- uint32_t start_sys;
- uint8_t type_of_loader;
- uint8_t loadflags;
- uint16_t setup_move_size;
- uint32_t code32_start;
- uint32_t ramdisk_image;
- uint32_t ramdisk_size;
- uint32_t bootsect_kludge;
- uint16_t head_end_ptr;
- uint16_t pad1;
- uint32_t cmd_line_ptr;
- uint32_t initrd_addr_max;
- uint32_t esdi;
- uint32_t edx;
-};
-
-struct setup_header *const shdr = (struct setup_header *)(LOW_SEG << 4);
-
/* Access to high memory */
/* Access to objects in the zero page */
@@ -209,7 +177,7 @@ static inline uint32_t rdz_32(uint32_t addr)
#define CMD_BOOL ((char *)-2) /* Found boolean option */
#define CMD_HASDATA(X) ((int)(X) >= 0)
-const char *getcmditem(const char *what)
+static const char *getcmditem(const char *what)
{
const char *p;
const char *wp = what;
@@ -277,18 +245,23 @@ void unzip_if_needed(uint32_t * where_p, uint32_t * size_p)
&orig_crc, &offset) == 0) {
if (offset + zbytes > size) {
- /* Assertion failure; check_zip is supposed to guarantee this
- never happens. */
- puts("internal error: check_zip returned nonsense\n");
- die();
+ /*
+ * Assertion failure; check_zip is supposed to guarantee this
+ * never happens.
+ */
+ die("internal error: check_zip returned nonsense\n");
}
- /* Find a good place to put it: search memory ranges in descending order
- until we find one that is legal and fits */
+ /*
+ * Find a good place to put it: search memory ranges in descending
+ * order until we find one that is legal and fits
+ */
okmem = 0;
for (i = nranges - 1; i >= 0; i--) {
- /* We can't use > 4G memory (32 bits only.) Truncate to 2^32-1
- so we don't have to deal with funny wraparound issues. */
+ /*
+ * We can't use > 4G memory (32 bits only.) Truncate to 2^32-1
+ * so we don't have to deal with funny wraparound issues.
+ */
/* Must be memory */
if (ranges[i].type != 1)
@@ -317,16 +290,25 @@ void unzip_if_needed(uint32_t * where_p, uint32_t * size_p)
if (startrange >= endrange)
continue;
- /* Must be large enough... don't rely on gzwhere for this (wraparound) */
+ /*
+ * Must be large enough... don't rely on gzwhere for this
+ * (wraparound)
+ */
if (endrange - startrange < gzdatasize)
continue;
- /* This is where the gz image should be put if we put it in this range */
+ /*
+ * This is where the gz image would be put if we put it in this
+ * range...
+ */
gzwhere = (endrange - gzdatasize) & ~(UNZIP_ALIGN - 1);
/* Cast to uint64_t just in case we're flush with the top byte */
if ((uint64_t) where + size >= gzwhere && where < endrange) {
- /* Need to move source data to avoid compressed/uncompressed overlap */
+ /*
+ * Need to move source data to avoid compressed/uncompressed
+ * overlap
+ */
uint32_t newwhere;
if (gzwhere - startrange < size)
@@ -336,9 +318,7 @@ void unzip_if_needed(uint32_t * where_p, uint32_t * size_p)
printf("Moving compressed data from 0x%08x to 0x%08x\n",
where, newwhere);
- /* Our memcpy() is OK, because we always move from a higher
- address to a lower one */
- memcpy((void *)newwhere, (void *)where, size);
+ memmove((void *)newwhere, (void *)where, size);
where = newwhere;
}
@@ -347,12 +327,9 @@ void unzip_if_needed(uint32_t * where_p, uint32_t * size_p)
break;
}
- if (!okmem) {
- printf
- ("Not enough memory to decompress image (need 0x%08x bytes)\n",
+ if (!okmem)
+ die("Not enough memory to decompress image (need 0x%08x bytes)\n",
gzdatasize);
- die();
- }
printf("gzip image: decompressed addr 0x%08x, len 0x%08x: ",
target, gzdatasize);
@@ -439,7 +416,7 @@ struct dosemu_header {
#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 const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size)
{
static struct geometry hd_geometry;
struct dosemu_header dosemu;
@@ -654,16 +631,6 @@ const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size)
}
/*
- * Jump here if all hope is gone...
- */
-void __attribute__ ((noreturn)) die(void)
-{
- asm volatile ("sti");
- for (;;)
- asm volatile ("hlt");
-}
-
-/*
* Find a $PnP installation check structure; return (ES << 16) + DI value
*/
static uint32_t pnp_install_check(void)
@@ -691,17 +658,66 @@ static uint32_t pnp_install_check(void)
return 0;
}
+/*
+ * Relocate the real-mode code to a new segment
+ */
+struct gdt_ptr {
+ uint16_t limit;
+ uint32_t base;
+} __attribute__((packed));
+
+static void set_seg_base(uint32_t gdt_base, int seg, uint32_t v)
+{
+ *(uint16_t *)(gdt_base + seg + 2) = v;
+ *(uint8_t *)(gdt_base + seg + 4) = v >> 16;
+ *(uint8_t *)(gdt_base + seg + 7) = v >> 24;
+}
+
+static void relocate_rm_code(uint32_t newbase)
+{
+ uint32_t gdt_base;
+ uint32_t oldbase = rm_args.rm_base;
+ uint32_t delta = newbase - oldbase;
+
+ cli();
+ memmove((void *)newbase, (void *)oldbase, rm_args.rm_size);
+
+ rm_args.rm_return += delta;
+ rm_args.rm_intcall += delta;
+ rm_args.rm_bounce += delta;
+ rm_args.rm_base += delta;
+ rm_args.rm_gdt += delta;
+ rm_args.rm_pmjmp += delta;
+ rm_args.rm_rmjmp += delta;
+
+ gdt_base = rm_args.rm_gdt;
+
+ *(uint32_t *)(gdt_base+2) = gdt_base; /* GDT self-pointer */
+
+ /* Segments 0x10 and 0x18 are real-mode-based */
+ set_seg_base(gdt_base, 0x10, rm_args.rm_base);
+ set_seg_base(gdt_base, 0x18, rm_args.rm_base);
+
+ asm volatile("lgdtl %0" : : "m" (*(char *)gdt_base));
+
+ *(uint32_t *)rm_args.rm_pmjmp += delta;
+ *(uint16_t *)rm_args.rm_rmjmp += delta >> 4;
+
+ rm_args.rm_handle_interrupt += delta;
+
+ sti();
+}
+
#define STACK_NEEDED 512 /* Number of bytes of stack */
+struct real_mode_args rm_args;
+
/*
* Actual setup routine
* Returns the drive number (which is then passed in %dl to the
* called routine.)
*/
-__cdecl syscall_t syscall;
-void *sys_bounce;
-
-__cdecl void setup(__cdecl syscall_t cs_syscall, void *cs_bounce)
+void setup(const struct real_mode_args *rm_args_ptr)
{
unsigned int bin_size;
char *memdisk_hook;
@@ -715,21 +731,23 @@ __cdecl void setup(__cdecl syscall_t cs_syscall, void *cs_bounce)
int total_size, cmdlinelen;
com32sys_t regs;
uint32_t ramdisk_image, ramdisk_size;
+ uint32_t boot_base, rm_base;
int bios_drives;
int do_edd = 1; /* 0 = no, 1 = yes, default is yes */
int no_bpt; /* No valid BPT presented */
+ uint32_t boot_seg = 0; /* Meaning 0000:7C00 */
+ uint32_t boot_len = 512; /* One sector */
+ uint32_t boot_lba = 0; /* LBA of bootstrap code */
- /* Set up global variables */
- syscall = cs_syscall;
- sys_bounce = cs_bounce;
+ /* We need to copy the rm_args into their proper place */
+ memcpy(&rm_args, rm_args_ptr, sizeof rm_args);
+ sti(); /* ... then interrupts are safe */
/* Show signs of life */
printf("%s %s\n", memdisk_version, copyright);
- if (!shdr->ramdisk_image || !shdr->ramdisk_size) {
- puts("MEMDISK: No ramdisk image specified!\n");
- die();
- }
+ if (!shdr->ramdisk_image || !shdr->ramdisk_size)
+ die("MEMDISK: No ramdisk image specified!\n");
ramdisk_image = shdr->ramdisk_image;
ramdisk_size = shdr->ramdisk_size;
@@ -895,10 +913,8 @@ __cdecl void setup(__cdecl syscall_t cs_syscall, void *cs_bounce)
printf("Total size needed = %u bytes, allocating %uK\n",
total_size, (total_size + 0x3ff) >> 10);
- if (total_size > dos_mem) {
- puts("MEMDISK: Insufficient low memory\n");
- die();
- }
+ if (total_size > dos_mem)
+ die("MEMDISK: Insufficient low memory\n");
driveraddr = stddosmem - total_size;
driveraddr &= ~0x3FF;
@@ -954,7 +970,7 @@ __cdecl void setup(__cdecl syscall_t cs_syscall, void *cs_bounce)
regs.es = 0;
regs.eax.b[1] = 0x08;
regs.edx.b[0] = geometry->driveno & 0x80;
- syscall(0x13, &regs, &regs);
+ intcall(0x13, &regs, &regs);
/* Note: per suggestion from the Interrupt List, consider
INT 13 08 to have failed if the sector count in CL is zero. */
@@ -1039,9 +1055,8 @@ __cdecl void setup(__cdecl syscall_t cs_syscall, void *cs_bounce)
wrz_8(BIOS_EQUIP, equip);
/* Install DPT pointer if this was the only floppy */
- if (getcmditem("dpt") != CMD_NOTFOUND || ((nflop == 1 || no_bpt)
- && getcmditem("nodpt") ==
- CMD_NOTFOUND)) {
+ if (getcmditem("dpt") != CMD_NOTFOUND ||
+ ((nflop == 1 || no_bpt) && getcmditem("nodpt") == CMD_NOTFOUND)) {
/* Do install a replacement DPT into INT 1Eh */
pptr->dpt_ptr = hptr->patch_offs + offsetof(struct patch_area, dpt);
}
@@ -1059,31 +1074,38 @@ __cdecl void setup(__cdecl syscall_t cs_syscall, void *cs_bounce)
printf("new: int13 = %08x int15 = %08x int1e = %08x\n",
rdz_32(BIOS_INT13), rdz_32(BIOS_INT15), rdz_32(BIOS_INT1E));
- /* Reboot into the new "disk"; this is also a test for the interrupt hooks */
+ /* Figure out entry point */
+ if (!boot_seg) {
+ boot_base = 0x7c00;
+ shdr->sssp = 0x7c00;
+ shdr->csip = 0x7c00;
+ } else {
+ boot_base = boot_seg << 4;
+ shdr->sssp = boot_seg << 16;
+ shdr->csip = boot_seg << 16;
+ }
+
+ /* Relocate the real-mode code to below the stub */
+ rm_base = (driveraddr - rm_args.rm_size) & ~15;
+ if (rm_base < boot_base + boot_len)
+ die("MEMDISK: bootstrap too large to load\n");
+
+ relocate_rm_code(rm_base);
+
+ /* Reboot into the new "disk" */
puts("Loading boot sector... ");
- memset(&regs, 0, sizeof regs);
- // regs.es = 0;
- regs.eax.w[0] = 0x0201; /* Read sector */
- regs.ebx.w[0] = 0x7c00; /* 0000:7C00 */
- regs.ecx.w[0] = 1; /* One sector */
- regs.edx.w[0] = geometry->driveno;
- syscall(0x13, &regs, &regs);
-
- if (regs.eflags.l & 1) {
- puts("MEMDISK: Failed to load new boot sector\n");
- die();
- }
+ memcpy((void *)boot_base, (char *)pptr->diskbuf + boot_lba*512, boot_len);
if (getcmditem("pause") != CMD_NOTFOUND) {
puts("press any key to boot... ");
regs.eax.w[0] = 0;
- syscall(0x16, &regs, NULL);
+ intcall(0x16, &regs, NULL);
}
puts("booting...\n");
/* On return the assembly code will jump to the boot vector */
shdr->esdi = pnp_install_check();
- shdr->edx = geometry->driveno;
+ shdr->edx = geometry->driveno;
}
diff --git a/memdisk/start32.S b/memdisk/start32.S
index 593ffb3e..4fb05374 100644
--- a/memdisk/start32.S
+++ b/memdisk/start32.S
@@ -15,6 +15,7 @@
* Simple stub to get us to the right point in the 32-bit code;
* this module must be linked first
*/
+
.section ".init", "ax"
.globl _start
_start:
@@ -26,4 +27,75 @@ _start:
xorl %eax, %eax
shrl $2, %ecx
rep ; stosl
- jmp setup
+
+ /* Set up the protected-mode IDT and the interrupt jump buffers */
+ movl $idt, %edi
+ movl $ijb, %eax
+ movl $0xee000000, %ebx /* Interrupt gate */
+ movw %cs, %bx /* Target segment */
+
+ /* Make the IDT */
+ movl $256, %ecx
+1:
+ stosl
+ stosl
+ movl %ebx, -6(%edi)
+ addl $8, %eax
+ loop 1b
+
+ /*
+ * Each entry in the interrupt jump buffer contains the following
+ * instructions:
+ *
+ * 60 pushal
+ * b0xx movb $xx, %al # interrupt number
+ * e9xxxxxxxx jmp handle_interrupt
+ */
+ movl $0xe900b060, %eax
+ movl $256, %ecx
+1:
+ movl %eax, (%edi)
+ addl $(1 << 16), %eax
+ movl $handle_interrupt-8, %edx
+ subl %edi, %edx
+ movl %edx, 4(%edi)
+ addl $8, %edi
+ loop 1b
+
+ lidtl idt_ptr
+
+ /* Save arguments, switch stacks */
+ movl %esp, %eax /* Pointer to arguments */
+ movl $__stack_end, %esp
+
+ call setup
+ jmp *(rm_args) /* First argument is return */
+
+ .section ".text","ax"
+ .globl intcall
+ .type intcall, @function
+intcall:
+ jmp *(rm_args+1*4) /* Intcall is argument 1 */
+ .size intcall, .-intcall
+
+ .type handle_interrupt, @function
+handle_interrupt:
+ jmp *(rm_args+4*4) /* Interrupt pointer is argument 4 */
+ .size handle_interrupt, .-handle_interrupt
+
+ .section ".rodata","a"
+idt_ptr:
+ .word 8*256-1
+ .long idt
+ .word 0
+
+ .section ".bss.large","aw"
+ .balign 2048
+idt:
+ .space 8*256
+ijb:
+ .space 8*256
+
+__stack:
+ .space 65536
+__stack_end:
diff --git a/memdisk/unzip.c b/memdisk/unzip.c
index 9f198a20..9144cf31 100644
--- a/memdisk/unzip.c
+++ b/memdisk/unzip.c
@@ -144,8 +144,7 @@ static int fill_inbuf(void)
{
/* This should never happen. We have already pointed the algorithm
to all the data we have. */
- printf("failed\nDecompression error: ran out of input data\n");
- die();
+ die("failed\nDecompression error: ran out of input data\n");
}
/* ===========================================================================
@@ -175,8 +174,7 @@ static void flush_window(void)
static void error(char *x)
{
- printf("failed\nDecompression error: %s\n", x);
- die();
+ die("failed\nDecompression error: %s\n", x);
}
/* GZIP header */
@@ -349,12 +347,14 @@ int check_zip(void *indata, uint32_t size, uint32_t * zbytes_p,
*/
extern void _end;
+static char heap[65536];
+
void *unzip(void *indata, uint32_t zbytes, uint32_t dbytes,
uint32_t orig_crc, void *target)
{
- /* Set up the heap; it's the 64K after the bounce buffer */
- free_mem_ptr = (ulg) sys_bounce + 0x10000;
- free_mem_end_ptr = free_mem_ptr + 0x10000;
+ /* Set up the heap; it is simply a chunk of bss memory */
+ free_mem_ptr = (size_t)heap;
+ free_mem_end_ptr = (size_t)heap + sizeof heap;
/* Set up input buffer */
inbuf = indata;