;
; ****************************************************************************
+
+%include "pxe.inc"
+
;
; Macros for byte order
;
mov ax,ds
mov es,ax
mov di,pxe_bootp_query_pkt
- mov bx,0071h ; PXENV_GET_CACHED_INFO
+ mov bx,PXENV_GET_CACHED_INFO
call far [PXENVEntry]
jc .pxe_err
mov eax,[bootp.yip]
mov [pxe_udp_open_pkt.sip],eax
mov di,pxe_udp_open_pkt
- mov bx,0030h ; PXENV_UDP_OPEN
+ mov bx,PXENV_UDP_OPEN
call far [PXENVEntry]
jc .failed
cmp word [pxe_udp_open_pkt.status], byte 0
mov cx,(kern_cmd_len+3) >> 2
rep movsd
;
-%ifdef debug
- push ds ; DEBUG DEBUG DEBUG
- push es
- pop ds
- mov si,offset cmd_line_here
- call cwritestr
- pop ds
- mov si,offset crlf_msg
- call cwritestr
-%endif
-;
; Scan through the command line for anything that looks like we might be
; interested in. The original version of this code automatically assumed
; the first option was BOOT_IMAGE=, but that is no longer certain.
push si ; mangle_dir mangles si
call mangle_name ; Mangle ramdisk name
pop si
- cmp byte [es:InitRD],' ' ; Null filename?
+ cmp byte [es:InitRD],0 ; Null filename?
seta byte [es:initrd_flag] ; Set flag if not
not_initrd: pop es ; Restore ES -> real_mode_seg
skip_this_opt: lodsb ; Load from command line
movzx ax,byte [es:bs_setupsecs] ; Variable # of setup sectors
mov [SetupSecs],ax
;
-; Now see if we have an initial RAMdisk; if so, do requisite computation
-;
- test byte [initrd_flag],1
- jz nk_noinitrd
- push es ; ES->real_mode_seg
- push ds
- pop es ; We need ES==DS
- mov si,InitRD
- mov di,InitRDCName
- call unmangle_name ; Create human-readable name
- sub di,InitRDCName
- mov [InitRDCNameLen],di
- mov di,InitRD
- call searchdir ; Look for it in directory
- pop es
- jz initrd_notthere
- mov [initrd_ptr],si ; Save cluster pointer
- mov [es:su_ramdisklen1],ax ; Ram disk length
- mov [es:su_ramdisklen2],dx
- div word [ClustSize]
- and dx,dx ; Round up
- setnz dl
- movzx dx,dl
- add ax,dx
- mov [InitRDClust],ax ; Ramdisk clusters
- mov edx,[HighMemSize] ; End of memory
- mov eax,HIGHMEM_MAX ; Limit imposed by kernel
- cmp edx,eax
- jna memsize_ok
- mov edx,eax ; Adjust to fit inside limit
-memsize_ok:
- sub edx,[es:su_ramdisklen] ; Subtract size of ramdisk
- xor dx,dx ; Round down to 64K boundary
- mov [InitRDat],edx ; Load address
- call loadinitrd ; Load initial ramdisk
- jmp short initrd_end
-
-initrd_notthere:
- mov si,err_noinitrd
- call cwritestr
- mov si,InitRDCName
- call cwritestr
- mov si,crlf_msg
- jmp abort_load
-
-no_high_mem: mov si,err_nohighmem ; Error routine
- jmp abort_load
-;
; About to load the kernel. This is a modern kernel, so use the boot flags
; we were provided.
;
-nk_noinitrd:
-initrd_end:
mov al,[es:su_loadflags]
mov [LoadFlags],al
;
mov eax,[HighMemSize]
sub eax,100000h ; Load address
cmp eax,[KernelSize]
- jb no_high_mem ; Not enough high memory
+ jb near no_high_mem ; Not enough high memory
;
; Move the stuff beyond the setup code to high memory at 100000h
;
add esi,(real_mode_seg << 4) ; Pointer to source
mov edi,100000h ; Copy to address 100000h
call bcopy ; Transfer to high memory
-;
+
push word xfer_buf_seg ; Transfer buffer segment
pop es
high_load_loop:
mov si,dot_msg
call cwritestr
+
+ call crlf
+;
+; Now see if we have an initial RAMdisk; if so, do requisite computation
+; We know we have a new kernel; the old_kernel code already will have objected
+; if we tried to load initrd using an old kernel
+;
+load_initrd:
+ test byte [initrd_flag],1
+ jz nk_noinitrd
+ push es ; ES->real_mode_seg
+ push ds
+ pop es ; We need ES==DS
+ mov si,InitRD
+ mov di,InitRDCName
+ call unmangle_name ; Create human-readable name
+ sub di,InitRDCName
+ mov [InitRDCNameLen],di
+ mov di,InitRD
+ call searchdir ; Look for it in directory
+ pop es
+ jz initrd_notthere
+ mov [initrd_ptr],si ; Save cluster pointer
+ mov [es:su_ramdisklen1],ax ; Ram disk length
+ mov [es:su_ramdisklen2],dx
+ div word [ClustSize]
+ and dx,dx ; Round up
+ setnz dl
+ movzx dx,dl
+ add ax,dx
+ mov [InitRDClust],ax ; Ramdisk clusters
+ mov edx,[HighMemSize] ; End of memory
+ mov eax,HIGHMEM_MAX ; Limit imposed by kernel
+ cmp edx,eax
+ jna memsize_ok
+ mov edx,eax ; Adjust to fit inside limit
+memsize_ok:
+ sub edx,[es:su_ramdisklen] ; Subtract size of ramdisk
+ xor dx,dx ; Round down to 64K boundary
+ mov [InitRDat],edx ; Load address
+ call loadinitrd ; Load initial ramdisk
+ jmp short initrd_end
+
+initrd_notthere:
+ mov si,err_noinitrd
+ call cwritestr
+ mov si,InitRDCName
+ call cwritestr
+ mov si,crlf_msg
+ jmp abort_load
+
+no_high_mem: mov si,err_nohighmem ; Error routine
+ jmp abort_load
+
+initrd_end:
+nk_noinitrd:
;
; Abandon hope, ye that enter here! We do no longer permit aborts.
;
call abort_check ; Last chance!!
;
+; Now we're as close to be done as we can be and still use our normal
+; routines, print a CRLF to end the row of dots
+;
+; mov si,crlf_msg
+; call cwritestr
+ mov si,ready_msg
+ call cwritestr
+;
; Unload PXE stack
;
+ mov al,'U'
+ call writechr
call unload_pxe
+ cli
+ xor ax,ax
+ mov ss,ax
+ mov sp,7C00h ; Set up a more normal stack
+ mov al,'L'
+ call writechr
+
;
; Copy real_mode stuff up to 90000h
;
mov cx,[SetupSecs]
inc cx ; Setup + boot sector
shl cx,7 ; Sectors -> dwords
+ xor si,si
+ xor di,di
fs rep movsd
;
; Some kernels in the 1.2 ballpark but pre-bzImage have more than 4
xor al,al
call slow_out
;
-; Now we're as close to be done as we can be and still use our normal
-; routines, print a CRLF to end the row of dots
-;
- mov si,crlf_msg
- call cwritestr
-;
-; If we're debugging, wait for a keypress so we can read any debug messages
-;
-%ifdef debug
- xor ax,ax
- int 16h
-%endif
-;
; Set up segment registers and the Linux real-mode stack
;
+ cli
mov ax,9000h
mov ds,ax
mov es,ax
;
; We're done... now RUN THAT KERNEL!!!!
;
+ mov ax,0E00h + 'X'
+ mov bx,0007h
+ int 10h
jmp setup_seg:setup_entry
;
; Load an older kernel. Older kernels always have 4 setup sectors, can't have
;
is_comboot_image:
and dx,dx
- jnz comboot_too_large
+ jnz short comboot_too_large
cmp ax,0ff00h ; Max size in bytes
jae comboot_too_large
call writechr
mov di,pxe_udp_write_pkt
- mov bx,0033h ; PXENV_UDP_WRITE
+ mov bx,PXENV_UDP_WRITE
call far [PXENVEntry]
jc near .failure
cmp word [pxe_udp_write_pkt.status],byte 0
mov [pxe_udp_read_pkt.dip],eax
mov [pxe_udp_read_pkt.lport],bx
mov di,pxe_udp_read_pkt
- mov bx,0032h ; PXENV_UDP_READ
+ mov bx,PXENV_UDP_READ
call far [PXENVEntry]
and ax,ax
jz .got_packet ; Wait for packet
mov word [pxe_udp_write_pkt.buffer],tftp_opt_err
mov word [pxe_udp_write_pkt.buffersize],tftp_opt_err_len
mov di,pxe_udp_write_pkt
- mov bx,0033h ; PXENV_UDP_WRITE
+ mov bx,PXENV_UDP_WRITE
call far [PXENVEntry]
.no_tsize: mov si,err_oldtftp
mov al,'G'
call writechr
-.packet_loop: push cx ; Save count
- push es ; Save buffer pointer
- push bx
+.packet_loop: push cx ; <A> Save count
+ push es ; <B> Save buffer pointer
+ push bx ; <C>
mov ax,ds
mov es,ax
; next packet to be sent.
mov cx,PKT_RETRY
-.send_ack: push cx
+.send_ack: push cx ; <D>
mov al,'a'
call writechr
call ack_packet ; Send ACK
jz .send_ok
- pop cx
+ pop cx ; <D>
loop .send_ack
jmp kaboom ; Failed to send ACK
int 1Ah ; Get current time
mov cx,PKT_TIMEOUT
-.send_loop: push cx
- push dx
+.send_loop: push cx ; <E>
+ push dx ; <F>
mov bx,packet_buf
mov [pxe_udp_read_pkt.buffer],bx
mov ax,[si+tftp_localport]
mov [pxe_udp_read_pkt.lport],ax
mov di,pxe_udp_read_pkt
- mov bx,0032h ; PXE_UDP_READ
- push si
+ mov bx,PXENV_UDP_READ
+ push si ; <G>
call far [PXENVEntry]
- pop si
+ pop si ; <G>
cmp ax,byte 0
je .recv_ok
loop .send_ack
jmp kaboom ; Forget it...
-.recv_ok: pop dx
- pop cx
+.recv_ok: pop dx ; <F>
+ pop cx ; <E>
mov al,'r'
call writechr
jmp .send_ok ; Reset timeout
.right_packet: ; It's the packet we want. We're also EOF if the size < 512.
- pop cx ; Don't need the retry count anymore
- mov al,'*'
- call writechr
+ pop cx ; <D> Don't need the retry count anymore
movzx ecx,word [pxe_udp_read_pkt.buffersize]
- sub cx,4
+ sub cx,byte 4
add [si+tftp_filepos],ecx
cmp cx,TFTP_BLOCKSIZE ; Is it a full block
jb .last_block
- pop di ; Get target buffer
- pop es
+ mov al,'+'
+ call writechr
+ pop di ; <C> Get target buffer
+ pop es ; <B>
+
+ cld
push si
mov si,packet_buf+4
mov cx,TFTP_BLOCKSIZE >> 2
mov bx,di
pop si
- pop cx
+ pop cx ; <A>
loop .packet_loop_jmp
; If we had the exact right number of bytes, always get
- ; one more packet to get the EOF packet and close the
- ; socket.
-
+ ; one more packet to get the (zero-byte) EOF packet and
+ ; close the socket.
mov eax,[si+tftp_filepos]
cmp [si+tftp_filesize],eax
je .packet_loop_jmp
call ack_packet
mov word [si],0 ; Socket closed
- pop di
- pop es
+ mov al,'*'
+ call writechr
+ ; Copy data
+ pop di ; <C>
+ pop es ; <B>
+
+ cld
mov si,packet_buf+4
- sub cx,byte 4
- movzx ecx,cx
- add dword [si+tftp_filepos],ecx
rep movsb
mov bx,di
xor si,si
- pop cx ; Not used
+ pop cx ; <A> Not used
stc ; EOF
ret
mov [pxe_udp_write_pkt.buffer],word ack_packet_buf
mov [pxe_udp_write_pkt.buffersize], word 4
mov di,pxe_udp_write_pkt
- mov bx,0033h ; PXE_UDP_WRITE
+ mov bx,PXENV_UDP_WRITE
call far [PXENVEntry]
cmp ax,byte 0 ; ZF = 1 if write OK
popad
; This function unloads the PXE and UNDI stacks.
;
unload_pxe:
- ret ; Are these safe or will we die?
mov di,pxe_udp_close_pkt
- mov bx,0031h ; PXE_UDP_CLOSE
- call far [PXENVEntry]
- mov di,pxe_undi_shutdown_pkt
- mov bx,0005h ; PXE_UNDI_SHUTDOWN
+ mov bx,PXENV_UDP_CLOSE
call far [PXENVEntry]
mov di,pxe_undi_shutdown_pkt
- mov bx,0076h ; PXE_STOP_BASE
+ mov bx,PXENV_UNDI_SHUTDOWN
call far [PXENVEntry]
mov di,pxe_unload_stack_pkt
- mov bx,0070h ; PXE_UNLOAD_STACK
- call far [PXENVEntry]
- mov di,pxe_undi_shutdown_pkt
- mov bx,0015h ; PXE_STOP_UNDI
+ mov bx,PXENV_UNLOAD_STACK
call far [PXENVEntry]
ret
apiver_str db 'PXE API version is ',0
pxeentry_msg db 'PXE entry point found (we hope) at ', 0
myipaddr_msg db 'My IP address seems to be ',0
+ready_msg db 13, 10, 'Ready to start kernel...', 13, 10, 0
trying_msg db 'Trying to load: ', 0
loading_msg db 'Loading ', 0
dotdot_msg db '.'