⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pxelinux.asm

📁 linux内核
💻 ASM
📖 第 1 页 / 共 4 页
字号:
; -*- fundamental -*- (asm-mode sucks); $Id$; ****************************************************************************;;  pxelinux.asm;;  A program to boot Linux kernels off a TFTP server using the Intel PXE;  network booting API.  It is based on the SYSLINUX boot loader for;  MS-DOS floppies.;;   Copyright (C) 1994-2005  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;  the Free Software Foundation, Inc., 53 Temple Place Ste 330,;  Boston MA 02111-1307, USA; either version 2 of the License, or;  (at your option) any later version; incorporated herein by reference.; ; ****************************************************************************%define IS_PXELINUX 1%include "macros.inc"%include "config.inc"%include "kernel.inc"%include "bios.inc"%include "tracers.inc"%include "pxe.inc"%include "layout.inc";; Some semi-configurable constants... change on your own risk.;my_id		equ pxelinux_idFILENAME_MAX_LG2 equ 7			; log2(Max filename size Including final null)FILENAME_MAX	equ (1 << FILENAME_MAX_LG2)NULLFILE	equ 0			; Zero byte == null file nameNULLOFFSET	equ 4			; Position in which to lookREBOOT_TIME	equ 5*60		; If failure, time until full reset%assign HIGHMEM_SLOP 128*1024		; Avoid this much memory near the topMAX_OPEN_LG2	equ 5			; log2(Max number of open sockets)MAX_OPEN	equ (1 << MAX_OPEN_LG2)PKTBUF_SIZE	equ (65536/MAX_OPEN)	; Per-socket packet buffer sizeTFTP_PORT	equ htons(69)		; Default TFTP port PKT_RETRY	equ 6			; Packet transmit retry countPKT_TIMEOUT	equ 12			; Initial timeout, timer ticks @ 55 ms; Desired TFTP block size; For Ethernet MTU is normally 1500.  Unfortunately there seems to; be a fair number of networks with "substandard" MTUs which break.; The code assumes TFTP_LARGEBLK <= 2K.TFTP_MTU	equ 1472TFTP_LARGEBLK	equ (TFTP_MTU-20-8-4)	; MTU - IP hdr - UDP hdr - TFTP hdr; Standard TFTP block sizeTFTP_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?SECTOR_SHIFT	equ TFTP_BLOCKSIZE_LG2SECTOR_SIZE	equ TFTP_BLOCKSIZE;; This is what we need to do when idle;%define HAVE_IDLE 1			; idle is not a noop%macro	RESET_IDLE 0	call reset_idle%endmacro%macro	DO_IDLE 0	call check_for_arp%endmacro;; TFTP operation codes;TFTP_RRQ	equ htons(1)		; Read requestTFTP_WRQ	equ htons(2)		; Write requestTFTP_DATA	equ htons(3)		; Data packetTFTP_ACK	equ htons(4)		; ACK packetTFTP_ERROR	equ htons(5)		; ERROR packetTFTP_OACK	equ htons(6)		; OACK packet;; TFTP error codes;TFTP_EUNDEF	equ htons(0)		; Unspecified errorTFTP_ENOTFOUND	equ htons(1)		; File not foundTFTP_EACCESS	equ htons(2)		; Access violationTFTP_ENOSPACE	equ htons(3)		; Disk fullTFTP_EBADOP	equ htons(4)		; Invalid TFTP operationTFTP_EBADID	equ htons(5)		; Unknown transferTFTP_EEXISTS	equ htons(6)		; File existsTFTP_ENOUSER	equ htons(7)		; No such userTFTP_EOPTNEG	equ htons(8)		; Option negotiation failure;; The following structure is used for "virtual kernels"; i.e. LILO-style; option labels.  The options we permit here are `kernel' and `append; Since there is no room in the bottom 64K for all of these, we; stick them at vk_seg:0000 and copy them down before we need them.;		struc vkernelvk_vname:	resb FILENAME_MAX	; Virtual name **MUST BE FIRST!**vk_rname:	resb FILENAME_MAX	; Real namevk_ipappend:	resb 1			; "IPAPPEND" flag		resb 1			; Padvk_appendlen:	resw 1		alignb 4vk_append:	resb max_cmd_len+1	; Command line		alignb 4vk_end:		equ $			; Should be <= vk_size		endstruc;; Segment assignments in the bottom 640K; 0000h - main code/data segment (and BIOS segment);real_mode_seg	equ 4000hvk_seg          equ 3000h		; Virtual kernelsxfer_buf_seg	equ 2000h		; Bounce buffer for I/O to high mempktbuf_seg	equ 1000h		; Packet buffers segmentscomboot_seg	equ real_mode_seg	; COMBOOT image loading zone;; BOOTP/DHCP packet pattern;		struc bootp_t		bootp:.opcode		resb 1			; BOOTP/DHCP "opcode".hardware	resb 1			; ARP hardware type.hardlen	resb 1			; Hardware address length.gatehops	resb 1			; Used by forwarders.ident		resd 1			; Transaction ID.seconds	resw 1			; Seconds elapsed.flags		resw 1			; Broadcast flags.cip		resd 1			; Client IP.yip		resd 1			; "Your" IP.sip		resd 1			; Next server IP.gip		resd 1			; Relay agent IP.macaddr	resb 16			; Client MAC address.sname		resb 64			; Server name (optional).bootfile	resb 128		; Boot file name.option_magic	resd 1			; Vendor option magic cookie.options	resb 1260		; Vendor options		endstruc	BOOTP_OPTION_MAGIC	equ htonl(0x63825363)	; See RFC 2132;; TFTP connection data structure.  Each one of these corresponds to a local; UDP port.  The size of this structure must be a power of 2.; HBO = host byte order; NBO = network byte order; (*) = written by options negotiation code, must be dword sized;		struc open_file_ttftp_localport	resw 1			; Local port number	(0 = not in use)tftp_remoteport	resw 1			; Remote port numbertftp_remoteip	resd 1			; Remote IP addresstftp_filepos	resd 1			; Bytes downloaded (including buffer)tftp_filesize	resd 1			; Total file size(*)tftp_blksize	resd 1			; Block size for this connection(*)tftp_bytesleft	resw 1			; Unclaimed data bytestftp_lastpkt	resw 1			; Sequence number of last packet (NBO)tftp_dataptr	resw 1			; Pointer to available data		resw 2			; Currently unusued		; At end since it should not be zeroed on socked closetftp_pktbuf	resw 1			; Packet buffer offset		endstruc%ifndef DEPEND%if (open_file_t_size & (open_file_t_size-1))%error "open_file_t is not a power of 2"%endif%endif; ---------------------------------------------------------------------------;   BEGIN CODE; ---------------------------------------------------------------------------;; Memory below this point is reserved for the BIOS and the MBR; 		section .earlybsstrackbufsize	equ 8192trackbuf	resb trackbufsize	; Track buffer goes heregetcbuf		resb trackbufsize		; ends at 4800h		; Put some large buffers here, before RBFG_brainfuck,		; where we can still carefully control the address		; assignments...		alignb open_file_t_sizeFiles		resb MAX_OPEN*open_file_t_size		alignb FILENAME_MAXBootFile	resb 256		; Boot file from DHCP packetConfigServer	resd 1			; Null prefix for mangled config nameConfigName	resb 256-4		; Configuration file from DHCP optionPathPrefix	resb 256		; Path prefix derived from boot fileDotQuadBuf	resb 16			; Buffer for dotted-quad IP addressIPOption	resb 80			; ip= option bufferInitStack	resd 1			; Pointer to reset stack (SS:SP)PXEStack	resd 1			; Saved stack during PXE call; Warning here: RBFG build 22 randomly overwrites memory location; [0x5680,0x576c), possibly more.  It seems that it gets confused and; screws up the pointer to its own internal packet buffer and starts; writing a received ARP packet into low memory.RBFG_brainfuck	resb 0E00h		section .latebss		alignb 4RebootTime	resd 1			; Reboot timeout, if set by optionStrucPtr	resd 1			; Pointer to PXENV+ or !PXE structureAPIVer		resw 1			; PXE API version foundIPOptionLen	resw 1			; Length of IPOptionIdleTimer	resw 1			; Time to check for ARP?LocalBootType	resw 1			; Local boot return codePktTimeout	resw 1			; Timeout for current packetRealBaseMem	resw 1			; Amount of DOS memory after freeingOverLoad	resb 1			; Set if DHCP packet uses "overloading"; The relative position of these fields matter!MACLen		resb 1			; MAC address lenMACType		resb 1			; MAC address typeMAC		resb 16			; Actual MAC addressBOOTIFStr	resb 7			; Space for "BOOTIF="MACStr		resb 3*17		; MAC address as a string;; PXE packets which don't need static initialization;		alignb 4pxe_unload_stack_pkt:.status:	resw 1			; Status.reserved:	resw 10			; Reservedpxe_unload_stack_pkt_len	equ $-pxe_unload_stack_pkt		alignb 16		; BOOTP/DHCP packet buffer		alignb 16packet_buf	resb 2048		; Transfer packetpacket_buf_size	equ $-packet_buf;; Constants for the xfer_buf_seg;; The xfer_buf_seg is also used to store message file buffers.  We; need two trackbuffers (text and graphics), plus a work buffer; for the graphics decompressor.;xbs_textbuf	equ 0			; Also hard-coded, do not changexbs_vgabuf	equ trackbufsizexbs_vgatmpbuf	equ 2*trackbufsize		section .text		;		; 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;; Primary entry point.;bootsec		equ $_start:		pushfd			; Paranoia... in case of return to PXE		pushad			; ... save as much state as possible		push ds		push es		push fs		push gs		xor ax,ax		mov ds,ax		mov es,ax	%ifndef DEPEND%if TEXT_START != 0x7c00		; This is uglier than it should be, but works around		; some NASM 0.98.38 bugs.		mov di,section..bcopy32.start		add di,__bcopy_size-4		lea si,[di-(TEXT_START-7C00h)]		lea cx,[di-(TEXT_START-4)]		shr cx,2		std			; Overlapping areas, copy backwards		rep movsd%endif%endif		jmp 0:_start1		; Canonicalize address_start1:		mov bp,sp		les bx,[bp+48]		; ES:BX -> !PXE or PXENV+ structure		; That is all pushed onto the PXE stack.  Save the pointer		; to it and switch to an internal stack.		mov [InitStack],sp		mov [InitStack+2],ss%if USE_PXE_PROVIDED_STACK		; Apparently some platforms go bonkers if we		; set up our own stack...		mov [BaseStack],sp		mov [BaseStack+4],ss%endif		cli			; Paranoia		lss esp,[BaseStack]		sti			; Stack set up and ready		cld			; Copy upwards;; Initialize screen (if we're using one);		; Now set up screen parameters		call adjust_screen		; Wipe the F-key area		mov al,NULLFILE		mov di,FKeyName		mov cx,10*(1 << FILENAME_MAX_LG2)		push es			; Save ES -> PXE structure		push ds			; ES <- DS		pop es		rep stosb		pop es			; Restore ES;; Tell the user we got this far;		mov si,syslinux_banner		call writestr		mov si,copyright_str		call writestr;; Assume API version 2.1, in case we find the !PXE structure without; finding the PXENV+ structure.  This should really look at the Base; Code ROM ID structure in have_pxe, but this is adequate for now --; if we have !PXE, we have to be 2.1 or higher, and we don't care; about higher versions than that.;		mov word [APIVer],0201h;; Now we need to find the !PXE structure.  It's *supposed* to be pointed; to by SS:[SP+4], but support INT 1Ah, AX=5650h method as well.; FIX: ES:BX should point to the PXENV+ structure on entry as well.; We should make that the second test, and not trash ES:BX...; 		cmp dword [es:bx], '!PXE'		je have_pxe		; Uh-oh, not there... try plan B		mov ax, 5650h%if USE_PXE_PROVIDED_STACK == 0		lss sp,[InitStack]%endif		int 1Ah					; May trash regs%if USE_PXE_PROVIDED_STACK == 0		lss esp,[BaseStack]%endif		jc no_pxe		cmp ax,564Eh		jne no_pxe		; Okay, that gave us the PXENV+ structure, find !PXE		; structure from that (if available)		cmp dword [es:bx], 'PXEN'		jne no_pxe		cmp word [es:bx+4], 'V+'		je have_pxenv		; Nothing there either.  Last-ditch: scan memory		call memory_scan_for_pxe_struct		; !PXE scan		jnc have_pxe		call memory_scan_for_pxenv_struct	; PXENV+ scan		jnc have_pxenvno_pxe:		mov si,err_nopxe		call writestr		jmp kaboomhave_pxenv:		mov [StrucPtr],bx		mov [StrucPtr+2],es		mov si,found_pxenv		call writestr		mov si,apiver_str		call writestr		mov ax,[es:bx+6]		mov [APIVer],ax		call writehex4		call crlf		cmp ax,0201h			; API version 2.1 or higher		jb old_api		mov si,bx		mov ax,es		les bx,[es:bx+28h]		; !PXE structure pointer		cmp dword [es:bx],'!PXE'		je have_pxe		; Nope, !PXE structure missing despite API 2.1+, or at least		; the pointer is missing.  Do a last-ditch attempt to find it.		call memory_scan_for_pxe_struct		jnc have_pxe		; Otherwise, no dice, use PXENV+ structure		mov bx,si		mov es,axold_api:	; Need to use a PXENV+ structure		mov si,using_pxenv_msg		call writestr		mov eax,[es:bx+0Ah]		; PXE RM API		mov [PXENVEntry],eax		mov si,undi_data_msg		call writestr		mov ax,[es:bx+20h]		call writehex4		call crlf		mov si,undi_data_len_msg		call writestr		mov ax,[es:bx+22h]		call writehex4		call crlf		mov si,undi_code_msg		call writestr		mov ax,[es:bx+24h]		call writehex4		call crlf		mov si,undi_code_len_msg		call writestr		mov ax,[es:bx+26h]		call writehex4		call crlf		; Compute base memory size from PXENV+ structure		xor esi,esi		movzx eax,word [es:bx+20h]	; UNDI data seg		cmp ax,[es:bx+24h]		; UNDI code seg		ja .use_data		mov ax,[es:bx+24h]		mov si,[es:bx+26h]		jmp short .combine.use_data:		mov si,[es:bx+22h].combine:		shl eax,4		add eax,esi		shr eax,10			; Convert to kilobytes		mov [RealBaseMem],ax		mov si,pxenventry_msg		call writestr		mov ax,[PXENVEntry+2]		call writehex4		mov al,':'		call writechr		mov ax,[PXENVEntry]		call writehex4		call crlf		jmp have_entrypointhave_pxe:		mov [StrucPtr],bx		mov [StrucPtr+2],es		mov eax,[es:bx+10h]		mov [PXEEntry],eax		mov si,undi_data_msg		call writestr		mov eax,[es:bx+2Ah]		call writehex8		call crlf		mov si,undi_data_len_msg		call writestr		mov ax,[es:bx+2Eh]		call writehex4		call crlf		mov si,undi_code_msg		call writestr		mov ax,[es:bx+32h]		call writehex8		call crlf		mov si,undi_code_len_msg		call writestr		mov ax,[es:bx+36h]		call writehex4		call crlf		; Compute base memory size from !PXE structure		xor esi,esi		mov eax,[es:bx+2Ah]		cmp eax,[es:bx+32h]		ja .use_data		mov eax,[es:bx+32h]		mov si,[es:bx+36h]		jmp short .combine.use_data:		mov si,[es:bx+2Eh].combine:		add eax,esi		shr eax,10		mov [RealBaseMem],ax		mov si,pxeentry_msg		call writestr		mov ax,[PXEEntry+2]		call writehex4		mov al,':'		call writechr		mov ax,[PXEEntry]		call writehex4		call crlfhave_entrypoint:		push cs		pop es				; Restore CS == DS == ES;; Network-specific initialization;		xor ax,ax		mov [LocalDomain],al		; No LocalDomain received;; Now attempt to get the BOOTP/DHCP packet that brought us life (and an IP; address).  This lives in the DHCPACK packet (query info 2).;query_bootp:		mov di,pxe_bootp_query_pkt_2		mov bx,PXENV_GET_CACHED_INFO		call pxenv		push word [pxe_bootp_query_pkt_2.status]		jc .pxe_err1		cmp ax,byte 0		je .pxe_ok.pxe_err1:		mov di,pxe_bootp_size_query_pkt		mov bx,PXENV_GET_CACHED_INFO		call pxenv		jc .pxe_err.pxe_size:		mov ax,[pxe_bootp_size_query_pkt.buffersize]		call writehex4		call crlf.pxe_err:		mov si,err_pxefailed		call writestr		call writehex4		mov al, ' '		call writechr		pop ax				; Status		call writehex4		call crlf		jmp kaboom			; We're dead.pxe_ok:		pop cx				; Forget status		mov cx,[pxe_bootp_query_pkt_2.buffersize]		call parse_dhcp			; Parse DHCP packet;; Save away MAC address (assume this is in query info 2.  If this; turns out to be problematic it might be better getting it from; the query info 1 packet.);.save_mac:		movzx cx,byte [trackbuf+bootp.hardlen]		mov [MACLen],cl		mov al,[trackbuf+bootp.hardware]		mov [MACType],al		mov si,trackbuf+bootp.macaddr		mov di,MAC		push cx		rep movsb		mov cx,MAC+16		sub cx,di		xor ax,ax		rep stosb				mov si,bootif_str		mov di,BOOTIFStr		mov cx,bootif_str_len		rep movsb			pop cx		mov si,MACType		inc cx		mov bx,hextbl_lower.hexify_mac:		lodsb		mov ah,al		shr al,4		xlatb		stosb		mov al,ah		and al,0Fh		xlatb		stosb		mov al,'-'		stosb		loop .hexify_mac		mov [di-1],byte 0		; Null-terminate and strip final colon;; Now, get the boot file and other info.  This lives in the CACHED_REPLY; packet (query info 3).;		mov [pxe_bootp_size_query_pkt.packettype], byte 3		mov di,pxe_bootp_query_pkt_3		mov bx,PXENV_GET_CACHED_INFO		call pxenv		push word [pxe_bootp_query_pkt_3.status]		jc .pxe_err1		cmp ax,byte 0		jne .pxe_err1		; Packet loaded OK...		pop cx				; Forget status		mov cx,[pxe_bootp_query_pkt_3.buffersize]		call parse_dhcp			; Parse DHCP packet;; Generate ip= option;		call genipopt;; Print IP address;		mov eax,[MyIP]		mov di,DotQuadBuf		push di		call gendotquad			; This takes network byte order input

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -