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

📄 pxelinux.asm

📁 linux内核
💻 ASM
📖 第 1 页 / 共 4 页
字号:
		xchg ah,al			; Convert to host byte order		ror eax,16			; (BSWAP doesn't work on 386)		xchg ah,al		mov si,myipaddr_msg		call writestr		call writehex8		mov al,' '		call writechr		pop si				; DotQuadBuf		call writestr		call crlf		mov si,IPOption		call writestr		call crlf;; Check to see if we got any PXELINUX-specific DHCP options; in particular,; if we didn't get the magic enable, do not recognize any other options.;check_dhcp_magic:		test byte [DHCPMagic], 1	; If we didn't get the magic enable...		jnz .got_magic		mov byte [DHCPMagic], 0		; If not, kill all other options.got_magic:	;; Initialize UDP stack;udp_init:		mov eax,[MyIP]		mov [pxe_udp_open_pkt.sip],eax		mov di,pxe_udp_open_pkt		mov bx,PXENV_UDP_OPEN		call pxenv		jc .failed		cmp word [pxe_udp_open_pkt.status], byte 0		je .success.failed:	mov si,err_udpinit		call writestr		jmp kaboom.success:;; Common initialization code;%include "init.inc"%include "cpuinit.inc";; Now we're all set to start with our *real* business.	First load the; configuration file (if any) and parse it.;; In previous versions I avoided using 32-bit registers because of a; rumour some BIOSes clobbered the upper half of 32-bit registers at; random.  I figure, though, that if there are any of those still left; they probably won't be trying to install Linux on them...;; The code is still ripe with 16-bitisms, though.  Not worth the hassle; to take'm out.  In fact, we may want to put them back if we're going; to boot ELKS at some point.;;; Store standard filename prefix;prefix:		test byte [DHCPMagic], 04h	; Did we get a path prefix option		jnz .got_prefix		mov si,BootFile		mov di,PathPrefix		cld		call strcpy		mov cx,di		sub cx,PathPrefix+1		std		lea si,[di-2]			; Skip final null!.find_alnum:	lodsb		or al,20h		cmp al,'.'			; Count . or - as alphanum		je .alnum		cmp al,'-'		je .alnum		cmp al,'0'		jb .notalnum		cmp al,'9'		jbe .alnum		cmp al,'a'		jb .notalnum		cmp al,'z'		ja .notalnum.alnum:		loop .find_alnum		dec si.notalnum:	mov byte [si+2],0		; Zero-terminate after delimiter		cld.got_prefix:		mov si,tftpprefix_msg		call writestr		mov si,PathPrefix		call writestr		call crlf;; Load configuration file;find_config:;; Begin looking for configuration file;config_scan:		mov di,ConfigServer		xor eax,eax		stosd				; The config file is always from the server		test byte [DHCPMagic], 02h		jz .no_option		; We got a DHCP option, try it first		mov si,trying_msg		call writestr		; mov di,ConfigName		; - already the case		mov si,di		call writestr		call crlf		mov di,ConfigServer		call open		jnz .success.no_option:		mov di,ConfigName		mov si,cfgprefix		mov cx,cfgprefix_len		rep movsb		; Try loading by MAC address		; Have to guess config file name		push di		mov si,MACStr		mov cx,(3*17+1)/2		rep movsw		mov si,trying_msg		call writestr		mov di,ConfigName		mov si,di		call writestr		call crlf		mov di,ConfigServer		call open		pop di		jnz .success.scan_ip:		mov cx,8		mov eax,[MyIP]		xchg ah,al			; Convert to host byte order		ror eax,16		xchg ah,al.hexify_loop:	rol eax,4		push eax		and al,0Fh		cmp al,10		jae .high.low:		add al,'0'		jmp short .char.high:		add al,'A'-10.char:		stosb		pop eax		loop .hexify_loop		mov cx,9			; Up to 9 attempts.tryagain:	mov byte [di],0		cmp cx,byte 1		jne .not_default		pusha		mov si,default_str		mov cx,default_len		rep movsb			; Copy "default" string		popa.not_default:	pusha		mov si,trying_msg		call writestr		mov di,ConfigName		mov si,di		call writestr		call crlf		mov di,ConfigServer		call open		popa		jnz .success		dec di		loop .tryagain		jmp no_config_file.success:;; Now we have the config file open.  Parse the config file and; run the user interface.;%include "ui.inc";; Linux kernel loading code is common.  However, we need to define; a couple of helper macros...;; Handle "ipappend" option%define HAVE_SPECIAL_APPEND%macro	SPECIAL_APPEND 0		test byte [IPAppend],01h	; ip=		jz .noipappend1		mov si,IPOption		mov cx,[IPOptionLen]		rep movsb		mov al,' '		stosb.noipappend1:		test byte [IPAppend],02h		jz .noipappend2		mov si,BOOTIFStr		call strcpy		mov byte [es:di-1],' '		; Replace null with space.noipappend2:%endmacro; Unload PXE stack%define HAVE_UNLOAD_PREP%macro	UNLOAD_PREP 0		call unload_pxe%endmacro%include "runkernel.inc";; COMBOOT-loading code;%include "comboot.inc"%include "com32.inc"%include "cmdline.inc";; Boot sector loading code;%include "bootsect.inc";; Boot to the local disk by returning the appropriate PXE magic.; AX contains the appropriate return code.;local_boot:		push cs		pop ds		mov [LocalBootType],ax		call vgaclearmode		mov si,localboot_msg		call writestr		; Restore the environment we were called with		lss sp,[InitStack]		pop gs		pop fs		pop es		pop ds		popad		mov ax,[cs:LocalBootType]		popfd		retf				; Return to PXE;; Abort loading code;%include "abort.inc";; kaboom: write a message and bail out.  Wait for quite a while,;	  or a user keypress, then do a hard reboot.;kaboom:		mov ax,cs		mov es,ax		mov ds,ax		lss esp,[BaseStack]		sti.patch:		mov si,bailmsg		call writestr		; Returns with AL = 0.drain:		call pollchar		jz .drained		call getchar		jmp short .drain.drained:		mov edi,[RebootTime]		mov al,[DHCPMagic]		and al,09h		; Magic+Timeout		cmp al,09h		je .time_set		mov edi,REBOOT_TIME.time_set:		mov cx,18.wait1:		push cx		mov ecx,edi.wait2:		mov dx,[BIOS_timer].wait3:		call pollchar		jnz .keypress		cmp dx,[BIOS_timer]		je .wait3		loop .wait2,ecx		mov al,'.'		call writechr		pop cx		loop .wait1.keypress:		call crlf		mov word [BIOS_magic],0	; Cold reboot		jmp 0F000h:0FFF0h	; Reset vector address;; memory_scan_for_pxe_struct:;;	If none of the standard methods find the !PXE structure, look for it;	by scanning memory.;;	On exit, if found:;		CF = 0, ES:BX -> !PXE structure;	Otherwise CF = 1, all registers saved;	memory_scan_for_pxe_struct:		push ds		pusha		mov ax,cs		mov ds,ax		mov si,trymempxe_msg		call writestr		mov ax,[BIOS_fbm]	; Starting segment		shl ax,(10-4)		; Kilobytes -> paragraphs;		mov ax,01000h		; Start to look here		dec ax			; To skip inc ax.mismatch:		inc ax		cmp ax,0A000h		; End of memory		jae .not_found		call writehex4		mov si,fourbs_msg		call writestr		mov es,ax		mov edx,[es:0]		cmp edx,'!PXE'		jne .mismatch		movzx cx,byte [es:4]	; Length of structure		cmp cl,08h		; Minimum length		jb .mismatch		push ax		xor ax,ax		xor si,si.checksum:	es lodsb		add ah,al		loop .checksum		pop ax		jnz .mismatch		; Checksum must == 0.found:		mov bp,sp		xor bx,bx		mov [bp+8],bx		; Save BX into stack frame (will be == 0)		mov ax,es		call writehex4		call crlf		popa		pop ds		clc		ret.not_found:	mov si,notfound_msg		call writestr		popa		pop ds		stc		ret;; memory_scan_for_pxenv_struct:;;	If none of the standard methods find the PXENV+ structure, look for it;	by scanning memory.;;	On exit, if found:;		CF = 0, ES:BX -> PXENV+ structure;	Otherwise CF = 1, all registers saved;	memory_scan_for_pxenv_struct:		pusha		mov si,trymempxenv_msg		call writestr;		mov ax,[BIOS_fbm]	; Starting segment;		shl ax,(10-4)		; Kilobytes -> paragraphs		mov ax,01000h		; Start to look here		dec ax			; To skip inc ax.mismatch:		inc ax		cmp ax,0A000h		; End of memory		jae .not_found		mov es,ax		mov edx,[es:0]		cmp edx,'PXEN'		jne .mismatch		mov dx,[es:4]		cmp dx,'V+'		jne .mismatch		movzx cx,byte [es:8]	; Length of structure		cmp cl,26h		; Minimum length		jb .mismatch		xor ax,ax		xor si,si.checksum:	es lodsb		add ah,al		loop .checksum		and ah,ah		jnz .mismatch		; Checksum must == 0.found:		mov bp,sp		mov [bp+8],bx		; Save BX into stack frame		mov ax,bx		call writehex4		call crlf		clc		ret.not_found:	mov si,notfound_msg		call writestr		popad		stc		ret;; searchdir:;;	Open a TFTP connection to the server ;;	     On entry:;		DS:DI	= mangled filename;	     If successful:;		ZF clear;		SI	= socket pointer;		DX:AX	= file length in bytes;	     If unsuccessful;		ZF set;searchdir:		push es		push bx		push cx		mov ax,ds		mov es,ax		mov si,di		push bp		mov bp,sp		call allocate_socket		jz .ret		mov ax,PKT_RETRY	; Retry counter		mov word [PktTimeout],PKT_TIMEOUT	; Initial timeout	.sendreq:	push ax			; [bp-2]  - Retry counter		push si			; [bp-4]  - File name 		mov di,packet_buf		mov [pxe_udp_write_pkt.buffer],di		mov ax,TFTP_RRQ		; TFTP opcode		stosw		lodsd			; EAX <- server override (if any)		and eax,eax		jnz .noprefix		; No prefix, and we have the server		push si			; Add common prefix		mov si,PathPrefix		call strcpy		dec di		pop si		mov eax,[ServerIP]	; Get default server.noprefix:		call strcpy		; Filename		mov [bx+tftp_remoteip],eax		push bx			; [bp-6]  - TFTP block		mov bx,[bx]		push bx			; [bp-8]  - TID (local port no)		mov [pxe_udp_write_pkt.status],byte 0		mov [pxe_udp_write_pkt.sip],eax		; Now figure out the gateway		xor eax,[MyIP]		and eax,[Netmask]		jz .nogwneeded		mov eax,[Gateway].nogwneeded:		mov [pxe_udp_write_pkt.gip],eax		mov [pxe_udp_write_pkt.lport],bx		mov ax,[ServerPort]		mov [pxe_udp_write_pkt.rport],ax		mov si,tftp_tail		mov cx,tftp_tail_len		rep movsb		sub di,packet_buf	; Get packet size		mov [pxe_udp_write_pkt.buffersize],di		mov di,pxe_udp_write_pkt		mov bx,PXENV_UDP_WRITE		call pxenv		jc .failure		cmp word [pxe_udp_write_pkt.status],byte 0		jne .failure		;		; Danger, Will Robinson!  We need to support timeout		; and retry lest we just lost a packet...		;		; Packet transmitted OK, now we need to receive.getpacket:	push word [PktTimeout]	; [bp-10]		push word [BIOS_timer]	; [bp-12].pkt_loop:	mov bx,[bp-8]		; TID		mov di,packet_buf		mov word [pxe_udp_read_pkt.status],0		mov [pxe_udp_read_pkt.buffer],di		mov [pxe_udp_read_pkt.buffer+2],ds		mov word [pxe_udp_read_pkt.buffersize],packet_buf_size		mov eax,[MyIP]		mov [pxe_udp_read_pkt.dip],eax		mov [pxe_udp_read_pkt.lport],bx		mov di,pxe_udp_read_pkt		mov bx,PXENV_UDP_READ		call pxenv		and ax,ax		jz .got_packet			; Wait for packet.no_packet:		mov dx,[BIOS_timer]		cmp dx,[bp-12]		je .pkt_loop		mov [bp-12],dx		dec word [bp-10]		; Timeout		jnz .pkt_loop		pop ax	; Adjust stack		pop ax		shl word [PktTimeout],1		; Exponential backoff		jmp .failure		.got_packet:		mov si,[bp-6]			; TFTP pointer		mov bx,[bp-8]			; TID		mov eax,[si+tftp_remoteip]		cmp [pxe_udp_read_pkt.sip],eax	; This is technically not to the TFTP spec?		jne .no_packet		; Got packet - reset timeout		mov word [PktTimeout],PKT_TIMEOUT		pop ax	; Adjust stack		pop ax		mov ax,[pxe_udp_read_pkt.rport]		mov [si+tftp_remoteport],ax		; filesize <- -1 == unknown		mov dword [si+tftp_filesize], -1		; Default blksize unless blksize option negotiated		mov word [si+tftp_blksize], TFTP_BLOCKSIZE		mov cx,[pxe_udp_read_pkt.buffersize]		sub cx,2		; CX <- bytes after opcode		jb .failure		; Garbled reply		mov si,packet_buf		lodsw		cmp ax, TFTP_ERROR		je .bailnow		; ERROR reply: don't try again		cmp ax, TFTP_OACK		jne .no_tsize		; Now we need to parse the OACK packet to get the transfer		; size.  SI -> first byte of options; CX -> byte count.parse_oack:		jcxz .no_tsize			; No options acked.get_opt_name:		mov di,si		mov bx,si.opt_name_loop:	lodsb		and al,al		jz .got_opt_name		or al,20h			; Convert to lowercase		stosb		loop .opt_name_loop		; We ran out, and no final null		jmp .err_reply.got_opt_name:	; si -> option value		dec cx				; bytes left in pkt		jz .err_reply			; Option w/o value		; Parse option pointed to by bx; guaranteed to be		; null-terminated.		push cx		push si		mov si,bx			; -> option name		mov bx,tftp_opt_table		mov cx,tftp_opts.opt_loop:		push cx		push si		mov di,[bx]			; Option pointer		mov cx,[bx+2]			; Option len		repe cmpsb		pop si		pop cx		je .get_value			; OK, known option		add bx,6		loop .opt_loop		pop si		pop cx		jmp .err_reply			; Non-negotiated option returned.get_value:	pop si				; si -> option value		pop cx				; cx -> bytes left in pkt		mov bx,[bx+4]			; Pointer to data target		add bx,[bp-6]			; TFTP socket pointer		xor eax,eax		xor edx,edx.value_loop:	lodsb		and al,al		jz .got_value		sub al,'0'		cmp al, 9		ja .err_reply			; Not a decimal digit		imul edx,10		add edx,eax		mov [bx],edx		loop .value_loop		; Ran out before final null, accept anyway		jmp short .done_pkt.got_value:		dec cx

⌨️ 快捷键说明

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