aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Aleaxander <Aleaxander@gmail.com>2009-07-28 08:56:27 +0800
committerLiu Aleaxander <Aleaxander@gmail.com>2009-07-28 08:56:27 +0800
commite3378ba7a06a2628dbde49cd39c3d2258f46c630 (patch)
treecf9be0eeb7bcc41414b325d90ffa9f66aabaf6e6
parent1052e638453f6913f17c5d25f796113202ccbf90 (diff)
downloadpxelinux-e3378ba7a06a2628dbde49cd39c3d2258f46c630.tar.gz
pxelinux-e3378ba7a06a2628dbde49cd39c3d2258f46c630.tar.xz
pxelinux-e3378ba7a06a2628dbde49cd39c3d2258f46c630.zip
Core:PXELINUX: parse_dhcp_options converted
-rw-r--r--core/debug.c16
-rw-r--r--core/extern.inc2
-rw-r--r--core/pxe.c77
-rw-r--r--core/pxelinux.asm66
4 files changed, 96 insertions, 65 deletions
diff --git a/core/debug.c b/core/debug.c
index dde42e77..e0359a0f 100644
--- a/core/debug.c
+++ b/core/debug.c
@@ -21,8 +21,12 @@ void dump16(void *buf)
p = (uint8_t *)buf;
printf(" ");
- for (i = 0; i < 16; i++)
- printf("%c", *p++);
+ for (i = 0; i < 16; i++) {
+ uint8_t c = *p++;
+ if (c < 0x20)
+ c = '.';
+ printf("%c", c);
+ }
printf("\n");
}
@@ -48,7 +52,11 @@ void dumpn(void *buf, int n)
p = (uint8_t *)buf;
printf(" ");
- for (i = 0; i < n; i++)
- printf("%c", *p++);
+ for (i = 0; i < n; i++) {
+ uint8_t c = *p++;
+ if (c < 0x20)
+ c = '.';
+ printf("%c", c);
+ }
printf("\n");
}
diff --git a/core/extern.inc b/core/extern.inc
index 5cf15e3e..b727968e 100644
--- a/core/extern.inc
+++ b/core/extern.inc
@@ -17,7 +17,7 @@
extern memory_scan_for_pxe_struct, memory_scan_for_pxenv_struct
extern gendotquad, pxe_load_config, try_load, allocate_socket
extern free_socket, ip_ok, mangle_name, ack_packet, pxe_get_cached_info
- extern udp_init, get_prefix, network_init
+ extern udp_init, get_prefix, network_init, parse_dhcp_options
; debug.c
extern debug, print_reg
diff --git a/core/pxe.c b/core/pxe.c
index 1e996c19..a9a357ed 100644
--- a/core/pxe.c
+++ b/core/pxe.c
@@ -101,6 +101,9 @@ extern char PathPrefix[];
extern char CurrentDirName[];
extern char LocalDomain[];
+extern void dhcp_option_list();
+extern void dhcp_option_list_end();
+
char *err_nopxe = "No !PXE or PXENV+ API found; we're dead...\n";
char *err_pxefailed = "PXE API call failed, error ";
char *err_udpinit = "Failed to initialize UDP stack\n";
@@ -112,6 +115,17 @@ char *get_packet_msg = "Getting cached packet ";
uint16_t NextSocket = 49152;
+com32sys_t temp;
+
+inline void pusha(com32sys_t *regs)
+{
+ memcpy(&temp, regs, sizeof temp);
+}
+
+inline void popa(com32sys_t *regs)
+{
+ memcpy(regs, &temp, sizeof temp);
+}
/*
* parse the ip_str and return the ip address with *res.
@@ -833,6 +847,69 @@ void get_prefix()
printf("%s%s\n", tftpprefix_msg, PathPrefix);
strcpy(CurrentDirName, PathPrefix);
}
+
+/*
+ ; Parse a sequence of DHCP options, pointed to by DS:SI; the field
+ ; size is CX -- some DHCP servers leave option fields unterminated
+ ; in violation of the spec.
+ ;
+ ; For parse_some_dhcp_options, DH contains the minimum value for
+ ; the option to recognize -- this is used to restrict parsing to
+ ; PXELINUX-specific options only.
+*/
+void parse_dhcp_options(com32sys_t *regs)
+{
+ int size = regs->ecx.w[0];
+ char *option = (char *)MK_PTR(regs->ds, regs->esi.w[0]);
+ char *p;
+ uint8_t c;
+ uint8_t opt_num;
+ uint8_t opt_len;
+ uint8_t opt_filter = regs->edx.b[1] == 208 ? 208 : 0;
+
+ while (size --) {
+ c = *option++;
+
+ if (!size)
+ break;
+ if (c == 0)
+ continue;
+ if (c == 0xff)
+ break;
+
+ /* Anything else will have a lenght filed */
+ opt_num = c; /* dl <- option number */
+ opt_len = *option++; /* c <- option lenght */
+ size = size - opt_len - 1;
+ if (size < 0)
+ break;
+ if (opt_num < opt_filter) { /* Is the option value valid */
+ option += opt_len; /* Try next */
+ continue;
+ }
+
+ p = (char *)dhcp_option_list;
+ while (p < dhcp_option_list_end) {
+ if (opt_num == *p) {
+ uint32_t fun_addr = *(uint16_t *)(p + 1);
+ pusha(regs);
+ regs->esi.w[0] = option;
+ regs->eax.w[0] = opt_len;
+ regs->edx.b[1] = opt_num;
+ call16(fun_addr, regs, NULL);
+ popa(regs);
+ break;
+ }
+
+ p += 3;
+ }
+
+ /* parse next */
+ option += opt_len;
+ }
+}
+
+
/*
* Network-specific initialization
diff --git a/core/pxelinux.asm b/core/pxelinux.asm
index a7e10535..ac310ac9 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -1610,13 +1610,13 @@ parse_dhcp:
lodsd
cmp eax, BOOTP_OPTION_MAGIC
jne .nooptions
- call parse_dhcp_options
+ pm_call parse_dhcp_options
.nooptions:
mov si, trackbuf+bootp.bootfile
test byte [OverLoad],1
jz .nofileoverload
mov cx,128
- call parse_dhcp_options
+ pm_call parse_dhcp_options
jmp short .parsed_file
.nofileoverload:
cmp byte [si], 0
@@ -1631,68 +1631,13 @@ parse_dhcp:
test byte [OverLoad],2
jz .nosnameoverload
mov cx,64
- call parse_dhcp_options
+ pm_call parse_dhcp_options
.nosnameoverload:
ret
-;
-; Parse a sequence of DHCP options, pointed to by DS:SI; the field
-; size is CX -- some DHCP servers leave option fields unterminated
-; in violation of the spec.
-;
-; For parse_some_dhcp_options, DH contains the minimum value for
-; the option to recognize -- this is used to restrict parsing to
-; PXELINUX-specific options only.
-;
-parse_dhcp_options:
- xor dx,dx
-
-parse_some_dhcp_options:
-.loop:
- and cx,cx
- jz .done
-
- lodsb
- dec cx
- jz .done ; Last byte; must be PAD, END or malformed
- cmp al, 0 ; PAD option
- je .loop
- cmp al,255 ; END option
- je .done
-
- ; Anything else will have a length field
- mov dl,al ; DL <- option number
- xor ax,ax
- lodsb ; AX <- option length
- dec cx
- sub cx,ax ; Decrement bytes left counter
- jb .done ; Malformed option: length > field size
-
- cmp dl,dh ; Is the option value valid?
- jb .opt_done
-
- mov bx,dhcp_option_list
-.find_option:
- cmp bx,dhcp_option_list_end
- jae .opt_done
- cmp dl,[bx]
- je .found_option
- add bx,3
- jmp .find_option
-.found_option:
- pushad
- call [bx+1]
- popad
-
-; Fall through
- ; Unknown option. Skip to the next one.
-.opt_done:
- add si,ax
- jmp .loop
-.done:
- ret
section .data16
+ global dhcp_option_list
dhcp_option_list:
section .text16
@@ -1744,7 +1689,7 @@ dopt_%2:
dopt 43, vendor_encaps
mov dh,208 ; Only recognize PXELINUX options
mov cx,ax ; Length of option = max bytes to parse
- call parse_some_dhcp_options ; Parse recursive structure
+ pm_call parse_dhcp_options ; Parse recursive structure
ret
dopt 52, option_overload
@@ -1826,6 +1771,7 @@ dhcp_copyoption:
ret
section .data16
+ global dhcp_option_list_end
dhcp_option_list_end:
section .text16