From b17a78c59d28b06b77b3a9af636664a7299adbc9 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sun, 30 Aug 2009 05:37:30 +0800 Subject: [PATCH] Core:pxelinux: unload_pxe converted. I found it's also better to convert the unload_pxe, but I am not sure I'm right. Signed-off-by: Liu Aleaxander --- com32/include/syslinux/pxe_api.h | 5 ++ core/bootsect.inc | 2 +- core/comboot.inc | 2 +- core/extern.inc | 3 + core/fs/pxe/pxe.c | 69 +++++++++++++++++- core/fs/pxe/pxe.h | 9 +-- core/include/core.h | 2 + core/pxeidle.inc | 12 +++- core/pxelinux.asm | 146 +-------------------------------------- 9 files changed, 98 insertions(+), 152 deletions(-) diff --git a/com32/include/syslinux/pxe_api.h b/com32/include/syslinux/pxe_api.h index 6c9efc2..fcc4f87 100644 --- a/com32/include/syslinux/pxe_api.h +++ b/com32/include/syslinux/pxe_api.h @@ -408,6 +408,11 @@ typedef struct s_PXENV_GET_FILE_SIZE { uint16_t FileHandle; uint32_t FileSize; } __packed t_PXENV_GET_FILE_SIZE; + +typedef struct s_PXENV_UNLOAD_STACK { + pxenv_status_t Status; + uint8_t reserved[10]; +} __packed t_PXENV_UNLOAD_STACK; #define PXENV_UNDI_ISR_IN_START 1 #define PXENV_UNDI_ISR_IN_PROCESS 2 diff --git a/core/bootsect.inc b/core/bootsect.inc index 4d70998..23b4fdb 100644 --- a/core/bootsect.inc +++ b/core/bootsect.inc @@ -80,7 +80,7 @@ load_bootsec: xor bx,bx %elif IS_PXELINUX mov byte [KeepPXE],03h ; Chainloading + keep PXE - call reset_pxe + pm_call reset_pxe lfs si,[InitStack] ; Put restore DS, EDX and ESI to the true initial values mov bx,[fs:si+6] diff --git a/core/comboot.inc b/core/comboot.inc index 731e432..72f642e 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -635,7 +635,7 @@ comapi_cleanup: test dl,3 setnz [KeepPXE] sub bp,sp ; unload_pxe may move the stack around - call unload_pxe + pm_call unload_pxe add bp,sp ; restore frame pointer... %elif IS_SYSLINUX || IS_EXTLINUX ; Restore original FDC table diff --git a/core/extern.inc b/core/extern.inc index 20adb76..6ce807a 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -19,4 +19,7 @@ ; dir.c extern opendir, readdir, closedir + ; pxe.c + extern unload_pxe, reset_pxe + %endif ; EXTERN_INC diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index 8c006fe..a453785 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -23,6 +23,16 @@ const uint8_t TimeoutTable[] = { 92, 110, 132, 159, 191, 229, 255, 255, 255, 255, 0 }; +/* PXE unload sequences */ +const uint8_t new_api_unload[] = { + PXENV_UDP_CLOSE, PXENV_UNDI_SHUTDOWN, + PXENV_UNLOAD_STACK, PXENV_STOP_UNDI, 0 +}; +const uint8_t old_api_unload[] = { + PXENV_UDP_CLOSE, PXENV_UNDI_SHUTDOWN, + PXENV_UNLOAD_STACK, PXENV_UNDI_CLEANUP, 0 +}; + struct tftp_options { const char *str_ptr; /* string pointer */ size_t offset; /* offset into socket structre */ @@ -1471,9 +1481,66 @@ static int pxe_fs_init(struct fs_info *fs) /* Network-specific initialization */ network_init(); - + return 0; } + +inline void reset_pxe(void) +{ + static __lowmem struct s_PXENV_UDP_CLOSE udp_close; + pxe_call(PXENV_UDP_CLOSE, &udp_close); +} + +/* + * This function unloads the PXE and UNDI stacks and + * unclaims the memory. + */ +void unload_pxe(void) +{ + uint8_t api; + const uint8_t *api_ptr; + uint16_t flag = 0; + int err; + int int_addr; + static __lowmem struct s_PXENV_UNLOAD_STACK unload_stack; + + if (KeepPXE) { + /* + * We want to keep PXE around, but still we should reset + * it to the standard bootup configuration. + */ + reset_pxe(); + return; + } + + api_ptr = major_ver(APIVer) >= 2 ? new_api_unload : old_api_unload; + while((api = *api_ptr++)) { + memset(&unload_stack, 0, sizeof unload_stack); + err = pxe_call(api, &unload_stack); + if (err || unload_stack.Status != PXENV_STATUS_SUCCESS) + goto cant_free; + } + + flag = 0xff00; + if (RealBaseMem <= BIOS_fbm) /* Santiy check */ + goto cant_free; + flag ++; + + /* Check that PXE actually unhooked the INT 0x1A chain */ + int_addr = (int)MK_PTR(*(uint16_t *)(4*0x1a+2), *(uint16_t *)(4*0x1a)); + int_addr >>= 10; + if (int_addr >= RealBaseMem || int_addr < BIOS_fbm) { + BIOS_fbm = RealBaseMem; + return; + } + +cant_free: + printf("Failed to free base memory error %04x-%08x\n", + flag, *(uint32_t *)(4 * 0x1a)); + return; +} + + const struct fs_ops pxe_fs_ops = { .fs_name = "pxe", diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h index 864815b..7c30d66 100644 --- a/core/fs/pxe/pxe.h +++ b/core/fs/pxe/pxe.h @@ -26,11 +26,12 @@ */ #define TFTP_PORT htons(69) /* Default TFTP port */ #define TFTP_BLOCKSIZE_LG2 9 -#define TFTP_BLOCKSIZE (1 << TFTP_BLOCKSIZE_LG2) -#define PKTBUF_SEG 0x4000 -#define PKTBUF_SIZE (65536 / MAX_OPEN) +#define TFTP_BLOCKSIZE (1 << TFTP_BLOCKSIZE_LG2) +#define PKTBUF_SEG 0x4000 +#define PKTBUF_SIZE (65536 / MAX_OPEN) -#define is_digit(c) (((c) >= '0') && ((c) <= '9')) +#define is_digit(c) (((c) >= '0') && ((c) <= '9')) +#define major_ver(v) (((v) >> 8) && 0xff) /* * TFTP operation codes diff --git a/core/include/core.h b/core/include/core.h index 52a35d4..61097a6 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -76,6 +76,7 @@ extern char DNSRecvBuf[]; extern uint16_t RealBaseMem; extern uint16_t APIVer; extern far_ptr_t PXEEntry; +extern uint8_t KeepPXE; extern far_ptr_t InitStack; @@ -84,6 +85,7 @@ extern uint8_t UUIDType; extern char UUID[]; extern volatile uint16_t BIOS_timer; +extern uint16_t BIOS_fbm; extern const uint8_t TimeoutTable[]; #endif /* CORE_H */ diff --git a/core/pxeidle.inc b/core/pxeidle.inc index ef3e1b7..4cfdc1b 100644 --- a/core/pxeidle.inc +++ b/core/pxeidle.inc @@ -18,8 +18,18 @@ ;; Query for the NIC type, and detect certain special cases. ;; - section .text16 + section .bss16 + pxe_udp_read_pkt: +.status: resw 1 ; Status +.sip: resd 1 ; Source IP +.dip: resd 1 ; Destination (our) IP +.rport: resw 1 ; Remote port +.lport: resw 1 ; Local port +.buffersize: resw 1 ; Max packet size +.buffer: resw 2 ; seg:off of buffer + + section .text16 ;; ;; Initializes the idle mechanism based on the device type ;; diff --git a/core/pxelinux.asm b/core/pxelinux.asm index 8f0b7ac..7643d00 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -127,17 +127,6 @@ UUIDType resb 1 ; Type byte from DHCP option UUID resb 16 ; UUID, from the PXE stack UUIDNull resb 1 ; dhcp_copyoption zero-terminates -; -; PXE packets which don't need static initialization -; - alignb 4 -pxe_unload_stack_pkt: -.status: resw 1 ; Status -.reserved: resb 10 ; Reserved -pxe_unload_stack_pkt_len equ $-pxe_unload_stack_pkt - - alignb 16 - ; BOOTP/DHCP packet buffer section .bss16 global packet_buf @@ -250,7 +239,7 @@ _start1: ; Unload PXE stack %define HAVE_UNLOAD_PREP %macro UNLOAD_PREP 0 - call unload_pxe + pm_call unload_pxe %endmacro ; @@ -397,104 +386,6 @@ pxe_int1a: %endif ret -; -; unload_pxe: -; -; 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 - - push ds - push es - - mov ax,cs - mov ds,ax - mov es,ax - - mov si,new_api_unload - cmp byte [APIVer+1],2 ; Major API version >= 2? - jae .new_api - mov si,old_api_unload -.new_api: - -.call_loop: xor ax,ax - lodsb - and ax,ax - jz .call_done - xchg bx,ax - mov di,pxe_unload_stack_pkt - push di - xor ax,ax - mov cx,pxe_unload_stack_pkt_len >> 1 - rep stosw - pop di - call pxenv - jc .cant_free - mov ax,word [pxe_unload_stack_pkt.status] - cmp ax,PXENV_STATUS_SUCCESS - jne .cant_free - jmp .call_loop - -.call_done: - mov bx,0FF00h - - mov dx,[RealBaseMem] - cmp dx,[BIOS_fbm] ; Sanity check - jna .cant_free - inc bx - - ; Check that PXE actually unhooked the INT 1Ah chain - movzx eax,word [4*0x1a] - movzx ecx,word [4*0x1a+2] - shl ecx,4 - add eax,ecx - shr eax,10 - cmp ax,dx ; Not in range - jae .ok - cmp ax,[BIOS_fbm] - jae .cant_free - ; inc bx - -.ok: - mov [BIOS_fbm],dx -.pop_ret: - pop es - pop ds - ret - -.cant_free: - mov si,cant_free_msg - call writestr_early - push ax - xchg bx,ax - call writehex4 - mov al,'-' - call writechr - pop ax - call writehex4 - mov al,'-' - call writechr - mov eax,[4*0x1a] - call writehex8 - call crlf - jmp .pop_ret - - ; 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 - mov bx,PXENV_UDP_CLOSE - mov di,pxe_udp_close_pkt - call pxenv - pop es - ret - - ; ----------------------------------------------------------------------------- ; Common modules @@ -541,45 +432,12 @@ exten_table_end: dd 0, 0 ; Need 8 null bytes here ; -; PXE unload sequences -; -new_api_unload: - db PXENV_UDP_CLOSE - db PXENV_UNDI_SHUTDOWN - db PXENV_UNLOAD_STACK - db PXENV_STOP_UNDI - db 0 -old_api_unload: - db PXENV_UDP_CLOSE - db PXENV_UNDI_SHUTDOWN - db PXENV_UNLOAD_STACK - db PXENV_UNDI_CLEANUP - db 0 - -; -; PXE query packets partially filled in -; - section .bss16 -pxe_udp_close_pkt: -.status: resw 1 ; Status - -pxe_udp_read_pkt: -.status: resw 1 ; Status -.sip: resd 1 ; Source IP -.dip: resd 1 ; Destination (our) IP -.rport: resw 1 ; Remote port -.lport: resw 1 ; Local port -.buffersize: resw 1 ; Max packet size -.buffer: resw 2 ; seg:off of buffer - - -; ; Misc initialized (data) variables ; section .data16 alignz 4 - global BaseStack + global BaseStack, KeepPXE BaseStack dd StackTop ; ESP of base stack dw 0 ; SS of base stack KeepPXE db 0 ; Should PXE be kept around? -- 2.7.4