aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Aleaxander <Aleaxander@gmail.com>2009-08-04 18:33:49 +0800
committerLiu Aleaxander <Aleaxander@gmail.com>2009-08-04 18:33:49 +0800
commitbfded9469080eb6752a5070605dce073da0e7d45 (patch)
tree79afe94f917517bccc70c4245f0a83b809e876e2
parent030c84480f275e2aa8c98c08de187185d522d252 (diff)
downloadpxelinux-bfded9469080eb6752a5070605dce073da0e7d45.tar.gz
pxelinux-bfded9469080eb6752a5070605dce073da0e7d45.tar.xz
pxelinux-bfded9469080eb6752a5070605dce073da0e7d45.zip
Core:PXELINUX: searchdir converted --- the real one
I made a mistake about the last commit; sorry for it. And now it works, at least for my situation. While I haven't had much situation to make a good test.( I'm just using Qemu)
-rw-r--r--core/pxe.c38
-rw-r--r--core/pxelinux.asm422
2 files changed, 19 insertions, 441 deletions
diff --git a/core/pxe.c b/core/pxe.c
index ff825e01..eec23fdf 100644
--- a/core/pxe.c
+++ b/core/pxe.c
@@ -1732,13 +1732,13 @@ int fill_tail(char *dst)
p += strlen(mode) + 1;
strcpy(p, tsize_str);
- p += tsize_len;
+ p += strlen(tsize_str) + 1;
- strcpy(p, blksize_str);
- p += blksize_len;
-
strcpy(p, "0");
p += 2;
+
+ strcpy(p, blksize_str);
+ p += strlen(blksize_str) + 1;
strcpy(p, asciidec);
p += strlen(asciidec) + 1;
@@ -1804,11 +1804,11 @@ void searchdir_c(com32sys_t *regs)
uint8_t timeout;
uint16_t oldtime;
uint16_t tid;
- uint16_t *data_ptr;
uint16_t opcode;
uint16_t blk_num;
uint32_t ip;
uint32_t filesize;
+ uint32_t *data_ptr;
init_options();
allocate_socket(regs);
@@ -1836,7 +1836,7 @@ void searchdir_c(com32sys_t *regs)
}
strcpy(buf, p); /* Copy the filename */
- buf += strlen(p);
+ buf += strlen(p) + 1; /* advance the pointer, null char included */
#if GPXE
if (is_gpxe(packet_buf + 2)) {
@@ -1845,6 +1845,7 @@ void searchdir_c(com32sys_t *regs)
fo->filename[1] = regs->ds;
err = pxe_call(PXENV_FILE_OPEN, fo);
if (err) {
+ regs->esi.w[0] = OFFS_WRT(file, 0);
free_socket(regs);
regs->eflags.l |= EFLAGS_ZF;
return;
@@ -1988,9 +1989,10 @@ void searchdir_c(com32sys_t *regs)
goto done_pkt;
dst = src = options;
- while (*src) {
+ while (buffersize--) {
+ if (*src == 0)
+ break; /* found a final null */
*dst++ = *src++ | 0x20;
- buffersize--;
if (!buffersize)
goto done_pkt; /* found no final null */
}
@@ -2010,21 +2012,18 @@ void searchdir_c(com32sys_t *regs)
goto err_reply; /* Non-negotitated option returned, no idea what it means ...*/
p += tftp_opt->str_len;
- buffersize -= tftp_opt->str_len;
-
+
/* get the address of the filed that we want to write on */
- data_ptr = (uint16_t *)((char *)file + tftp_opt->offset);
+ data_ptr = (uint32_t *)((char *)file + tftp_opt->offset);
+ *data_ptr = 0;
/* do convert a number-string to decimal number, just like atoi */
- while (*p) {
+ while (buffersize--) {
+ if (*p == 0)
+ break; /* found a final null */
if (*p > '9')
goto err_reply; /* Not a decimal digit */
- *data_ptr = *data_ptr * 10 + *p - '0';
-
- buffersize --;
- if (!buffersize)
- goto done_pkt;
- p++;
+ *data_ptr = *data_ptr * 10 + *p++ - '0';
}
}while (buffersize);
@@ -2043,7 +2042,8 @@ void searchdir_c(com32sys_t *regs)
}
done_pkt:
- regs->eax.l = file->tftp_filesize;
+ regs->eax.l = file->tftp_filesize;
+ regs->esi.w[0] = OFFS_WRT(file, 0);
got_file:
regs->eflags.l &= ~EFLAGS_ZF;
if (!file->tftp_filesize) {
diff --git a/core/pxelinux.asm b/core/pxelinux.asm
index a7bed544..a86e452a 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -453,431 +453,9 @@ close_file:
mov word [si],0 ; Not in use
.closed: ret
-%if 0
searchdir:
pm_call searchdir_c
ret
-%else
-;
-; searchdir:
-;
-; Open a TFTP connection to the server
-;
-; On entry:
-; DS:DI = mangled filename
-; If successful:
-; ZF clear
-; SI = socket pointer
-; EAX = file length in bytes, or -1 if unknown
-; 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
-
- pm_call allocate_socket
- jz .ret
-
- mov ax,TimeoutTable ; Reset timeout
-
-.sendreq: push ax ; [bp-2] - Timeout pointer
- 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
-%if GPXE
- mov si,packet_buf+2
- call is_gpxe
- jnc .gpxe
-%endif
-
- 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.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: mov bx,[bp-2]
- movzx bx,byte [bx]
- push bx ; [bp-10] - timeout in ticks
- push word [BIOS_timer] ; [bp-12]
-
-.pkt_loop: mov bx,[bp-8] ; TID
- mov di,packet_buf
- 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
- jnc .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]
- jnz .pkt_loop
- pop ax ; Adjust stack
- pop ax
- jmp .failure
-
-.got_packet:
- mov si,[bp-6] ; TFTP pointer
- mov bx,[bp-8] ; TID
-
- ; Make sure the packet actually came from the server
- ; This is technically not to the TFTP spec?
- mov eax,[si+tftp_remoteip]
- cmp [pxe_udp_read_pkt.sip],eax
- jne .no_packet
-
- ; Got packet - reset timeout
- mov word [bp-2],TimeoutTable
-
- 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
-
- movzx ecx,word [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
-
- ; If the server doesn't support any options, we'll get
- ; a DATA reply instead of OACK. Stash the data in
- ; the file buffer and go with the default value for
- ; all options...
- cmp ax, TFTP_DATA
- je .no_oack
-
- cmp ax, TFTP_OACK
- jne .err_reply ; Unknown packet type
-
- ; Now we need to parse the OACK packet to get the transfer
- ; and packet sizes.
- ; SI -> first byte of options; [E]CX -> byte count
-.parse_oack:
- jcxz .done_pkt ; No options acked
-
-.get_opt_name:
- ; If we find an option which starts with a NUL byte,
- ; (a null option), we're either seeing garbage that some
- ; TFTP servers add to the end of the packet, or we have
- ; no clue how to parse the rest of the packet (what is
- ; an option name and what is a value?) In either case,
- ; discard the rest.
- cmp byte [si],0
- je .done_pkt
-
- 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 .done_pkt ; Ignore runt option
-.got_opt_name: ; si -> option value
- dec cx ; bytes left in pkt
- jz .done_pkt ; Option w/o value, ignore
-
- ; 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
- ; Non-negotiated option returned, no idea what it means...
- jmp .err_reply
-
-.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
- jnz .get_opt_name ; Not end of packet
-
- ; ZF == 1
-
- ; Success, done!
-.done_pkt:
- pop si ; Junk
- pop si ; We want the packet ptr in SI
-
- mov eax,[si+tftp_filesize]
-.got_file: ; SI->socket structure, EAX = size
- and eax,eax ; Set ZF depending on file size
- jz .error_si ; ZF = 1 need to free the socket
-.ret:
- leave ; SP <- BP, POP BP
- pop cx
- pop bx
- pop es
- ret
-
-
-.no_oack: ; We got a DATA packet, meaning no options are
- ; suported. Save the data away and consider the length
- ; undefined, *unless* this is the only data packet...
- mov bx,[bp-6] ; File pointer
- sub cx,2 ; Too short?
- jb .failure
- lodsw ; Block number
- cmp ax,htons(1)
- jne .failure
- mov [bx+tftp_lastpkt],ax
- cmp cx,TFTP_BLOCKSIZE
- ja .err_reply ; Corrupt...
- je .not_eof
- ; This was the final EOF packet, already...
- ; We know the filesize, but we also want to ack the
- ; packet and set the EOF flag.
- mov [bx+tftp_filesize],ecx
- mov byte [bx+tftp_goteof],1
- push si
- mov si,bx
- ; AX = htons(1) already
- pm_call ack_packet
- pop si
-.not_eof:
- mov [bx+tftp_bytesleft],cx
- mov ax,pktbuf_seg
- push es
- mov es,ax
- mov di,tftp_pktbuf
- mov [bx+tftp_dataptr],di
- add cx,3
- shr cx,2
- rep movsd
- pop es
- jmp .done_pkt
-
-.err_reply: ; TFTP protocol error. Send ERROR reply.
- ; ServerIP and gateway are already programmed in
- mov si,[bp-6]
- mov ax,[si+tftp_remoteport]
- mov word [pxe_udp_write_pkt.rport],ax
- mov word [pxe_udp_write_pkt.buffer],tftp_proto_err
- mov word [pxe_udp_write_pkt.buffersize],tftp_proto_err_len
- mov di,pxe_udp_write_pkt
- mov bx,PXENV_UDP_WRITE
- call pxenv
-
- ; Write an error message and explode
- mov si,err_damage
- call writestr_early
- jmp kaboom
-
-.bailnow:
- ; Immediate error - no retry
- mov word [bp-2],TimeoutTableEnd-1
-
-.failure: pop bx ; Junk
- pop bx
- pop si
- pop ax
- inc ax
- cmp ax,TimeoutTableEnd
- jb .sendreq ; Try again
-
-.error: mov si,bx ; Socket pointer
-.error_si: ; Socket pointer already in SI
- pm_call free_socket ; ZF <- 1, SI <- 0
- jmp .ret
-
-
-
-
-%if GPXE
-.gpxe:
- push bx ; Socket pointer
- mov di,gpxe_file_open
- mov word [di],2 ; PXENV_STATUS_BAD_FUNC
- mov word [di+4],packet_buf+2 ; Completed URL
- mov [di+6],ds
- mov bx,PXENV_FILE_OPEN
- call pxenv
- pop si ; Socket pointer in SI
- jc .error_si
-
- mov ax,[di+2]
- mov word [si+tftp_localport],-1 ; gPXE URL
- mov [si+tftp_remoteport],ax
- mov di,gpxe_get_file_size
- mov [di+2],ax
-
-%if 0
- ; Disable this for now since gPXE doesn't always
- ; return valid information in PXENV_GET_FILE_SIZE
- mov bx,PXENV_GET_FILE_SIZE
- call pxenv
- mov eax,[di+4] ; File size
- jnc .oksize
-%endif
- or eax,-1 ; Size unknown
-.oksize:
- mov [si+tftp_filesize],eax
- jmp .got_file
-%endif ; GPXE
-
-%endif
-
-%if GPXE
-;
-; is_gpxe: Return CF=0 if and only if the buffer pointed to by
-; DS:SI is a URL (contains ://) *and* the gPXE extensions
-; API is available. No registers modified.
-;
-is_gpxe:
- pm_call is_url
- jc .ret ; Not a URL, don't bother
-.again:
- cmp byte [HasGPXE],1
- ja .unknown
- ; 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:
- mov si,gpxe_warning_msg
- call writestr_early
-.done:
- mov [HasGPXE],bh
- popad
- pop es
- jmp .again
-
- section .data16
-gpxe_warning_msg:
- db 'URL syntax, but gPXE extensions not detected, '
- db 'trying plain TFTP...', CR, LF, 0
-HasGPXE db -1 ; Unknown
- section .text16
-
-%endif
-
;
; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled