aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/kernel.inc2
-rw-r--r--core/ldlinux.asm35
-rw-r--r--core/pxe.inc1
-rw-r--r--core/pxelinux.asm319
-rw-r--r--core/runkernel.inc18
5 files changed, 245 insertions, 130 deletions
diff --git a/core/kernel.inc b/core/kernel.inc
index 9b888cc8..5e1c7a39 100644
--- a/core/kernel.inc
+++ b/core/kernel.inc
@@ -85,6 +85,8 @@ HEADER_ID equ 'HdrS' ; HdrS (in littleendian hex)
; Flags for the su_loadflags field
;
LOAD_HIGH equ 01h ; Large kernel, load high
+QUIET_FLAG equ 20h ; Quiet the kernel
+KEEP_SEGMENTS equ 40h ; Don't reload segments
CAN_USE_HEAP equ 80h ; Boot loader reports heap size
;
diff --git a/core/ldlinux.asm b/core/ldlinux.asm
index ba7e8040..0808e6e8 100644
--- a/core/ldlinux.asm
+++ b/core/ldlinux.asm
@@ -116,6 +116,7 @@ RootDirSize resd 1 ; Root dir size in sectors
TotalSectors resd 1 ; Total number of sectors
ClustSize resd 1 ; Bytes/cluster
ClustMask resd 1 ; Sectors/cluster - 1
+Clusters resd 1 ; Total number of clusters
CopySuper resb 1 ; Distinguish .bs versus .bss
DriveNumber resb 1 ; BIOS drive number
ClustShift resb 1 ; Shift count for sectors/cluster
@@ -183,24 +184,31 @@ getfattype:
sub eax,[DataArea]
shr eax,cl ; cl == ClustShift
mov cl,nextcluster_fat12-(nextcluster+2)
- cmp eax,4085 ; FAT12 limit
- jb .setsize
+ cmp eax,0xFF4 ; FAT12 limit
+ jbe .setsize
mov cl,nextcluster_fat16-(nextcluster+2)
- cmp eax,65525 ; FAT16 limit
- jb .setsize
+ cmp eax,0xFFF4 ; FAT16 limit
+ jbe .setsize
;
; FAT32, root directory is a cluster chain
;
+ mov ecx,0x0FFFFFF4 ; Max possible cluster count
+ cmp eax,ecx
+ jb .oksize
+ mov eax,ecx
+.oksize:
+
mov cl,[ClustShift]
- mov eax,[bootsec+44] ; Root directory cluster
- sub eax,2
- shl eax,cl
- add eax,[DataArea]
- mov [RootDir],eax
+ mov edx,[bootsec+44] ; Root directory cluster
+ sub edx,2
+ shl edx,cl
+ add edx,[DataArea]
+ mov [RootDir],edx
mov cl,nextcluster_fat28-(nextcluster+2)
mov byte [SuperSize],superblock_len_fat32
.setsize:
mov byte [nextcluster+1],cl
+ mov [Clusters],eax ; Total clusters
;
; Common initialization code
@@ -1242,7 +1250,8 @@ nextcluster_fat12:
shr cx,4
.even: and cx,0FFFh
movzx edi,cx
- cmp di,0FF0h
+ lea ax,[di-2]
+ cmp ax,[Clusters]
pop si
pop cx
pop bx
@@ -1264,7 +1273,8 @@ nextcluster_fat16:
add bx,bx
and bx,1FEh
movzx edi,word [gs:si+bx]
- cmp di,0FFF0h
+ lea ax,[di-2]
+ cmp ax,[Clusters]
pop bx
pop si
pop eax
@@ -1285,7 +1295,8 @@ nextcluster_fat28:
and bx,1FCh
mov edi,dword [gs:si+bx]
and edi,0FFFFFFFh ; 28 bits only
- cmp edi,0FFFFFF0h
+ lea eax,[edi-2]
+ cmp eax,[Clusters]
pop bx
pop si
pop eax
diff --git a/core/pxe.inc b/core/pxe.inc
index 7471c4f0..2fd1edb7 100644
--- a/core/pxe.inc
+++ b/core/pxe.inc
@@ -71,6 +71,7 @@
%define PXENV_GET_FILE_SIZE 0x00e4
%define PXENV_FILE_EXEC 0x00e5
%define PXENV_FILE_API_CHECK 0x00e6
+%define PXENV_FILE_EXIT_HOOK 0x00e7
; Exit codes
%define PXENV_EXIT_SUCCESS 0x0000
diff --git a/core/pxelinux.asm b/core/pxelinux.asm
index 651dd4c3..01159f16 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -8,7 +8,7 @@
; MS-DOS floppies.
;
; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-; Copyright 2009 Intel Corporation; author: H. Peter Anvin
+; Copyright 2009-2010 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
@@ -48,7 +48,7 @@ TFTP_LARGEBLK equ (TFTP_MTU-20-8-4) ; MTU - IP hdr - UDP hdr - TFTP hdr
; Standard TFTP block size
TFTP_BLOCKSIZE_LG2 equ 9 ; log2(bytes/block)
TFTP_BLOCKSIZE equ (1 << TFTP_BLOCKSIZE_LG2)
-%assign USE_PXE_PROVIDED_STACK 1 ; Use stack provided by PXE?
+%assign USE_PXE_PROVIDED_STACK 0 ; Use stack provided by PXE?
SECTOR_SHIFT equ TFTP_BLOCKSIZE_LG2
SECTOR_SIZE equ TFTP_BLOCKSIZE
@@ -217,7 +217,7 @@ packet_buf_size equ $-packet_buf
; PXELINUX needs more BSS than the other derivatives;
; therefore we relocate it from 7C00h on startup.
;
-StackBuf equ $ ; Base of stack if we use our own
+StackBuf equ $-44 ; Base of stack if we use our own
;
; Primary entry point.
@@ -332,80 +332,7 @@ adhcp_copy:
mov si,copyright_str
call writestr_early
-;
-; Look to see if we are on an EFI CSM system. Some EFI
-; CSM systems put the BEV stack in low memory, which means
-; a return to the PXE stack will crash the system. However,
-; INT 18h works reliably, so in that case hack the stack and
-; point the "return address" to an INT 18h instruction.
-;
-; Hack the stack instead of the much simpler "just invoke INT 18h
-; if we want to reset", so that chainloading other NBPs will work.
-;
-efi_csm_workaround:
- les bp,[InitStack] ; GS:SP -> original stack
- les bx,[es:bp+44] ; Return address
- cmp word [es:bx],18CDh ; Already pointing to INT 18h?
- je .skip
- ; Search memory from E0000 to FFFFF for a $EFI structure
- mov bx,0E000h
-.scan_mem:
- mov es,bx
- cmp dword [es:0],'IFE$' ; $EFI is byte-reversed...
- jne .not_here
- ;
- ; Verify the table. We don't check the checksum because
- ; it seems some CSMs leave it at zero.
- ;
- movzx cx,byte [es:5] ; Table length
- cmp cx,83 ; 83 bytes is the current length...
- jae .found_it
-
-.not_here:
- inc bx
- jnz .scan_mem
- jmp .skip ; No $EFI structure found
-
- ;
- ; Found a $EFI structure. Move down the original stack
- ; and put an INT 18h instruction there instead.
- ;
-.found_it:
-%if USE_PXE_PROVIDED_STACK
- mov cx,efi_csm_hack_size
- mov si,sp
- sub sp,cx
- mov di,sp
- mov ax,ss
- mov es,ax
- sub [InitStack],cx
- sub [BaseStack],cx
-%else
- les si,[InitStack]
- lea di,[si-efi_csm_hack_size]
- mov [InitStack],di
-%endif
- lea cx,[bp+52] ; End of the stack we care about
- sub cx,si
- es rep movsb
- mov [es:di-8],di ; Clobber the return address
- mov [es:di-6],es
- mov si,efi_csm_hack
- mov cx,efi_csm_hack_size
- rep movsb
-
-.skip:
-
- section .data
- alignz 4
-efi_csm_hack:
- int 18h
- jmp 0F000h:0FFF0h
- hlt
-efi_csm_hack_size equ $-efi_csm_hack
-
- section .text
;
; Assume API version 2.1, in case we find the !PXE structure without
@@ -751,6 +678,33 @@ udp_init:
.success:
;
+; Check to see if we're using gPXE
+;
+%if GPXE
+ ; If we get here, the gPXE status is unknown.
+ mov di,gpxe_file_api_check
+ mov bx,PXENV_FILE_API_CHECK ; BH = 0
+ call pxenv
+ jc .nogood
+ cmp dword [di+4],0xe9c17b20
+ jne .nogood
+ mov eax,[di+12]
+ mov [GPXEFuncs],eax
+ not ax ; Set bits of *missing* functions...
+ and ax,01001011b ; The functions we care about
+ setz bh
+.nogood:
+ mov [HasGPXE],bh
+
+ section .data
+ alignb 4
+GPXEFuncs dd 0
+HasGPXE db 0
+
+ section .text
+%endif
+
+;
; Common initialization code
;
%include "cpuinit.inc"
@@ -1599,42 +1553,31 @@ is_gpxe:
jc .ret ; Not a URL, don't bother
.again:
cmp byte [HasGPXE],1
- ja .unknown
+ jnb .ret
; CF=1 if not available (0),
; CF=0 if known available (1).
-.ret: ret
-.unknown:
- ; If we get here, the gPXE status is unknown.
- push es
- pushad
- push ds
- pop es
- mov di,gpxe_file_api_check
- mov bx,PXENV_FILE_API_CHECK ; BH = 0
- call pxenv
- jc .nogood
- cmp dword [di+4],0xe9c17b20
- jne .nogood
- mov ax,[di+12] ; Don't care about the upper half...
- not ax ; Set bits of *missing* functions...
- and ax,01001011b ; The functions we care about
- setz bh
- jz .done
-.nogood:
+ inc word [GPXEWarningCtr]
+ jnz .skip
+
+ push si
mov si,gpxe_warning_msg
- call writestr_early
-.done:
- mov [HasGPXE],bh
- popad
- pop es
- jmp .again
+ call writestr
+ pop si
+.skip:
+ stc
+
+.ret: ret
+
section .data
+ alignz 2
+GPXEWarningCtr:
+ dw -1 ; Print msg when it goes to 0
gpxe_warning_msg:
db 'URL syntax, but gPXE extensions not detected, '
db 'trying plain TFTP...', CR, LF, 0
-HasGPXE db -1 ; Unknown
+
section .text
%endif
@@ -2152,10 +2095,11 @@ get_packet_gpxe:
; This function unloads the PXE and UNDI stacks and unclaims
; the memory.
;
-unload_pxe:
- cmp byte [KeepPXE],0 ; Should we keep PXE around?
- jne reset_pxe
+reset_pxe:
+ or byte [KeepPXE],1
+ ; Fall through
+unload_pxe:
push ds
push es
@@ -2163,6 +2107,9 @@ unload_pxe:
mov ds,ax
mov es,ax
+ cmp byte [KeepPXE],0 ; Should we keep PXE around?
+ jne do_reset_pxe
+
mov si,new_api_unload
cmp byte [APIVer+1],2 ; Major API version >= 2?
jae .new_api
@@ -2233,16 +2180,168 @@ unload_pxe:
; We want to keep PXE around, but still we should reset
; it to the standard bootup configuration
-reset_pxe:
- push es
- push cs
- pop es
+do_reset_pxe:
+ TRACER 'A'
+
mov bx,PXENV_UDP_CLOSE
mov di,pxe_udp_close_pkt
call pxenv
+
+ TRACER 'B'
+
+%if GPXE
+ test byte [GPXEFuncs],80h ; gPXE special unload?
+ jz .plain
+
+ TRACER 'C'
+
+ mov bx,PXENV_FILE_EXIT_HOOK
+ mov di,pxe_file_exit_hook
+ call pxenv
+ jc .plain
+
+ TRACER 'D'
+
+ ; Now we actually need to exit back to gPXE, which will
+ ; give control back to us on the *new* "original stack"...
+ pushfd
+ pushad
+ push ds
+ push fs
+ push gs
+ mov [PXEStack],sp
+ mov [PXEStack+2],ss
+ lss sp,[InitStack]
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ popad
+ popfd
+ xor ax,ax
+ retf
+.resume:
+ cli
+
+ TRACER 'E'
+
+ ; gPXE will have a stack frame looking much like our
+ ; InitStack, except it has a magic cookie at the top,
+ ; and the segment registers are in reverse order.
+ pop eax
+ pop ax
+ pop bx
+ pop cx
+ pop dx
+ push ax
+ push bx
+ push cx
+ push dx
+ mov [cs:InitStack],sp
+ mov [cs:InitStack+2],ss
+ lss sp,[cs:PXEStack]
+ pop gs
+ pop fs
+ pop ds
+ popad
+ popfd
+%endif ; GPXE
+
+.plain:
+ TRACER 'F'
+
+;
+; Look to see if we are on an EFI CSM system. Some EFI
+; CSM systems put the BEV stack in low memory, which means
+; a return to the PXE stack will crash the system. However,
+; INT 18h works reliably, so in that case hack the stack and
+; point the "return address" to an INT 18h instruction.
+;
+; Hack the stack instead of the much simpler "just invoke INT 18h
+; if we want to reset", so that chainloading other NBPs will work.
+;
+efi_csm_workaround:
+ les bp,[InitStack] ; ES:BP -> original stack
+ les bx,[es:bp+44] ; ES:BX -> Return address
+ cmp word [es:bx],18CDh ; Already pointing to INT 18h?
+ je .skip
+
+ ; Search memory from E0000 to FFFFF for a $EFI structure
+ mov bx,0E000h
+.scan_mem:
+ mov es,bx
+ cmp dword [es:0],'IFE$' ; $EFI is byte-reversed...
+ jne .not_here
+ ;
+ ; Verify the table. We don't check the checksum because
+ ; it seems some CSMs leave it at zero.
+ ;
+ movzx cx,byte [es:5] ; Table length
+ cmp cx,83 ; 83 bytes is the current length...
+ jae .found_it
+
+.not_here:
+ inc bx
+ jnz .scan_mem
+ jmp .skip ; No $EFI structure found
+
+ ;
+ ; Found a $EFI structure. Move down the original stack
+ ; and put an INT 18h instruction there instead.
+ ;
+.found_it:
+%if USE_PXE_PROVIDED_STACK
+ mov cx,efi_csm_hack_size
+ mov si,sp
+ sub sp,cx
+ mov di,sp
+ mov ax,ss
+ mov es,ax
+ sub [InitStack],cx
+ sub [BaseStack],cx
+%else
+ les si,[InitStack]
+ lea di,[si-efi_csm_hack_size]
+ mov [InitStack],di
+%endif
+ lea cx,[bp+52] ; End of the stack we care about
+ sub cx,si
+ es rep movsb
+ mov [es:di-8],di ; Clobber the return address
+ mov [es:di-6],es
+ mov si,efi_csm_hack
+ mov cx,efi_csm_hack_size
+ rep movsb
+
+.skip:
+ TRACER 'G'
+
+.done:
pop es
+ pop ds
ret
+
+ section .data
+ alignz 4
+efi_csm_hack:
+ int 18h
+ jmp 0F000h:0FFF0h
+ hlt
+efi_csm_hack_size equ $-efi_csm_hack
+
+
+
+%if GPXE
+ alignz 4
+pxe_file_exit_hook:
+.status: dw 0
+.offset: dw do_reset_pxe.resume
+.seg: dw 0
+%endif
+
+ section .text
+
;
; gendotquad
;
diff --git a/core/runkernel.inc b/core/runkernel.inc
index f6ede382..e738706f 100644
--- a/core/runkernel.inc
+++ b/core/runkernel.inc
@@ -1,7 +1,7 @@
;; -----------------------------------------------------------------------
;;
;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
+;; Copyright 2009-2010 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
@@ -140,16 +140,16 @@ parse_cmdline:
opt_vga:
mov ax,[es:di-1]
mov bx,-1
- cmp ax,'=nor' ; vga=normal
+ cmp ax,'=n' ; vga=normal
je .vc0
dec bx ; bx <- -2
- cmp ax,'=ext' ; vga=ext
+ cmp ax,'=e' ; vga=ext
je .vc0
dec bx ; bx <- -3
- cmp ax,'=ask' ; vga=ask
+ cmp ax,'=a' ; vga=ask
je .vc0
mov bx,0x0f04 ; bx <- 0x0f04 (current mode)
- cmp ax,'=cur' ; vga=current
+ cmp ax,'=c' ; vga=current
je .vc0
call parseint_esdi ; vga=<number>
jc .skip ; Not an integer
@@ -168,7 +168,7 @@ opt_mem:
ret
opt_quiet:
- mov byte [QuietBoot],1
+ mov byte [QuietBoot],QUIET_FLAG
ret
%if IS_PXELINUX
@@ -228,6 +228,8 @@ new_kernel:
; we were provided.
;
mov al,[es:su_loadflags]
+ or al,[QuietBoot] ; Set QUIET_FLAG if needed
+ mov [es:su_loadflags],al
mov [LoadFlags],al
any_kernel:
@@ -458,7 +460,7 @@ setup_move:
; BX points to the final real mode segment, and will be loaded
; into DS.
- test byte [QuietBoot],01h ; Don't clear the mode if quiet
+ test byte [QuietBoot],QUIET_FLAG
jz replace_bootstrap
jmp replace_bootstrap_noclearmode
@@ -631,7 +633,7 @@ loadinitrd:
; assumes CS == DS
;
writestr_qchk:
- test byte [QuietBoot],01h
+ test byte [QuietBoot],QUIET_FLAG
jz writestr
ret