Date: Wed, 16 Jan 2013 01:49:08 +0000 (UTC) From: Sean Bruno <sbruno@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r245486 - in user/sbruno/pxestuff/sys/boot/i386: . btx/btx btx/lib libi386 pxehttp Message-ID: <201301160149.r0G1n8Wl026588@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sbruno Date: Wed Jan 16 01:49:07 2013 New Revision: 245486 URL: http://svnweb.freebsd.org/changeset/base/245486 Log: First day of work on pxe_http restoral, merge in some janky assembly that better get some serious reviews from people whom are way smarter than I. Added: user/sbruno/pxestuff/sys/boot/i386/pxehttp/ user/sbruno/pxestuff/sys/boot/i386/pxehttp/Makefile user/sbruno/pxestuff/sys/boot/i386/pxehttp/README user/sbruno/pxestuff/sys/boot/i386/pxehttp/httpfs.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/httpfs.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_arp.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_arp.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_await.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_await.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_buffer.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_buffer.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_connection.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_connection.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_core.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_core.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_dhcp.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_dhcp.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_dns.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_dns.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_filter.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_filter.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_http.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_http.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_httpls.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_httpls.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_icmp.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_icmp.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_ip.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_ip.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_ip6.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_isr.S user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_isr.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_mem.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_mem.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_segment.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_segment.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_sock.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_sock.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_tcp.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_tcp.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_udp.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/pxe_udp.h user/sbruno/pxestuff/sys/boot/i386/pxehttp/socketfs.c user/sbruno/pxestuff/sys/boot/i386/pxehttp/socketfs.h Modified: user/sbruno/pxestuff/sys/boot/i386/Makefile user/sbruno/pxestuff/sys/boot/i386/btx/btx/btx.S user/sbruno/pxestuff/sys/boot/i386/btx/lib/btxsys.s user/sbruno/pxestuff/sys/boot/i386/btx/lib/btxv86.h user/sbruno/pxestuff/sys/boot/i386/libi386/Makefile Modified: user/sbruno/pxestuff/sys/boot/i386/Makefile ============================================================================== --- user/sbruno/pxestuff/sys/boot/i386/Makefile Wed Jan 16 01:30:46 2013 (r245485) +++ user/sbruno/pxestuff/sys/boot/i386/Makefile Wed Jan 16 01:49:07 2013 (r245486) @@ -3,7 +3,7 @@ .include <bsd.own.mk> SUBDIR= mbr pmbr boot0 boot0sio btx boot2 cdboot gptboot kgzldr \ - libi386 libfirewire loader + libi386 libfirewire pxehttp loader # special boot programs, 'self-extracting boot2+loader' SUBDIR+= pxeldr Modified: user/sbruno/pxestuff/sys/boot/i386/btx/btx/btx.S ============================================================================== --- user/sbruno/pxestuff/sys/boot/i386/btx/btx/btx.S Wed Jan 16 01:30:46 2013 (r245485) +++ user/sbruno/pxestuff/sys/boot/i386/btx/btx/btx.S Wed Jan 16 01:49:07 2013 (r245486) @@ -52,7 +52,8 @@ .set SEL_RDATA,0x20 # Real mode data .set SEL_UCODE,0x28|3 # User code .set SEL_UDATA,0x30|3 # User data - .set SEL_TSS,0x38 # TSS + .set SEL_TSS,0x38 # TSS + .set SEL_CALLGATE,0x40 # super2user callgate /* * Task state segment fields. */ @@ -62,8 +63,9 @@ /* * System calls. */ - .set SYS_EXIT,0x0 # Exit - .set SYS_EXEC,0x1 # Exec + .set SYS_EXIT,0x0 # Exit + .set SYS_EXEC,0x1 # Exec + .set SYS_ISR_INSTALL,0x2 # ISR_install /* * Fields in V86 interface structure. */ @@ -366,7 +368,6 @@ except.2: pushl 0x50(%esp,1) # Set ESP popl %es # data movl %esp,%ebx # Stack frame movl $dmpfmt,%esi # Dump format string - movl $MEM_BUF,%edi # Buffer pushl %edi # Dump to call dump # buffer popl %esi # and @@ -690,7 +691,9 @@ rret_tramp.3: popl %es # Restore /* * System Call. */ -intx30: cmpl $SYS_EXEC,%eax # Exec system call? +intx30: cmpl $SYS_ISR_INSTALL, %eax # is isr_install? + je intx30.2 # yes + cmpl $SYS_EXEC,%eax # Exec system call? jne intx30.1 # No pushl %ss # Set up popl %es # all @@ -708,6 +711,74 @@ intx30: cmpl $SYS_EXEC,%eax # Exec sys intx30.1: orb $0x1,%ss:btx_hdr+0x7 # Flag reboot jmp exit # Exit /* + * Here we need to modify IDT in such way, that at interrupt handle + * will be run isr_trump, which role is to run provided function + * in user space. + */ +intx30.2: + cli + pushl %edi + pushl %ebx + pushw %ds + pushw %dx + + pushl %ss # Set up + popl %ds # registers + + + movl $MEM_USR,%ebx # User base address + addl 0x18(%esp,1),%ebx # getting user stack head + addl $0x04, %ebx # first parameter + + movl (%ebx), %eax + movw 0x2(%ebx), %dx + xchgw %dx, %bx + +/* + * updating call gate + */ + movl $callgate, %edi + movw %ax, (%edi) # +0: store offset 00..15 + shr $0x10 ,%eax # getting high word + movw %ax, 0x06(%edi) # +6: handler offset 16..31 +/* + * installing handler + */ +/* + * NOTE: it seems nothing else must be done + */ + popw %dx + popw %ds + popl %ebx + popl %edi + sti + iret # return from syscall + +user_isr_call: +/* + * NOTE: isr must use lret to return and restore SS, ESP, CS, EIP. +*/ + pushl %ds # saving ds + pushl %edi + movl $SEL_SDATA, %eax # + movl %eax, %ds + + movl $callgate, %edi + movw (%edi), %ax + popl %edi + + cmpw $0x0000, %ax + je isr_ret + + lcall $SEL_CALLGATE,$0x00000000 # far call via callgate selector + # offset is ignored +isr_ret: + + + popl %ds + + iret # return from interrupt handler +/* * Dump structure [EBX] to [EDI], using format string [ESI]. */ dump.0: stosb # Save char @@ -1000,6 +1071,7 @@ gdt: .word 0x0,0x0,0x0,0x0 # Null entr .word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE .word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA tss_desc: .word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS +callgate: .word 0x0, SEL_UCODE,0xec00,0x0 # SEL_CALLGATE gdt.1: /* * Pseudo-descriptors. Modified: user/sbruno/pxestuff/sys/boot/i386/btx/lib/btxsys.s ============================================================================== --- user/sbruno/pxestuff/sys/boot/i386/btx/lib/btxsys.s Wed Jan 16 01:30:46 2013 (r245485) +++ user/sbruno/pxestuff/sys/boot/i386/btx/lib/btxsys.s Wed Jan 16 01:49:07 2013 (r245486) @@ -24,6 +24,7 @@ # .global __exit .global __exec + .global __isr_install # # Constants. # @@ -38,3 +39,8 @@ __exit: xorl %eax,%eax # BTX system # __exec: movl $0x1,%eax # BTX system int $INT_SYS # call 0x1 +# +# System call: isr_install +# +__isr_install: movl $0x2,%eax # BTX system + int $INT_SYS # call 0x2 Modified: user/sbruno/pxestuff/sys/boot/i386/btx/lib/btxv86.h ============================================================================== --- user/sbruno/pxestuff/sys/boot/i386/btx/lib/btxv86.h Wed Jan 16 01:30:46 2013 (r245485) +++ user/sbruno/pxestuff/sys/boot/i386/btx/lib/btxv86.h Wed Jan 16 01:49:07 2013 (r245486) @@ -64,4 +64,9 @@ extern u_int32_t __args; void __exit(int) __attribute__((__noreturn__)); void __exec(caddr_t, ...); +/* + * Installs interrupt handler function for interrupt int_num. + * caddr_t - in userspace. + */ +void __isr_install(caddr_t isr, uint16_t int_num); #endif /* !_BTXV86_H_ */ Modified: user/sbruno/pxestuff/sys/boot/i386/libi386/Makefile ============================================================================== --- user/sbruno/pxestuff/sys/boot/i386/libi386/Makefile Wed Jan 16 01:30:46 2013 (r245485) +++ user/sbruno/pxestuff/sys/boot/i386/libi386/Makefile Wed Jan 16 01:49:07 2013 (r245486) @@ -48,7 +48,7 @@ CFLAGS+= -Dalloca=__builtin_alloca CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../common \ -I${.CURDIR}/../btx/lib \ -I${.CURDIR}/../../../contrib/dev/acpica/include \ - -I${.CURDIR}/../../.. -I. + -I${.CURDIR}/../../.. -I. -I${.CURDIR}/../pxe_http/ # the location of libstand CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/ Added: user/sbruno/pxestuff/sys/boot/i386/pxehttp/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/sbruno/pxestuff/sys/boot/i386/pxehttp/Makefile Wed Jan 16 01:49:07 2013 (r245486) @@ -0,0 +1,50 @@ +# pxe_http project +# +LIB= pxe_http +INTERNALLIB= + +SRCS= pxe_isr.S pxe_mem.c pxe_buffer.c pxe_await.c pxe_arp.c pxe_ip.c \ + pxe_core.c pxe_icmp.c pxe_udp.c pxe_filter.c pxe_dns.c \ + pxe_dhcp.c pxe_segment.c pxe_tcp.c pxe_sock.c \ + pxe_connection.c pxe_http.c pxe_httpls.c httpfs.c + +CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../btx/lib \ + -I${.CURDIR}/../../../contrib/dev/acpica \ + -I${.CURDIR}/../../.. -I. -I$(.CURDIR)/.. -I${.CURDIR}/../libi386/ +# the location of libstand +CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/ + +#debug flag +#CFLAGS+= -DPXE_DEBUG +#CFLAGS+= -DPXE_DEBUG_HELL + +# core module debug +#CFLAGS+= -DPXE_CORE_DEBUG_HELL +#CFLAGS+= -DPXE_CORE_DEBUG +# TCP module debug +#CFLAGS+= -DPXE_TCP_DEBUG +#CFLAGS+= -DPXE_TCP_DEBUG_HELL +# IP module debug +#CFLAGS+= -DPXE_IP_DEBUG +#CFLAGS+= -DPXE_IP_DEBUG_HELL +# ARP module debug +#CFLAGS+= -DPXE_ARP_DEBUG +#CFLAGS+= -DPXE_ARP_DEBUG_HELL +# httpfs module +#CFLAGS+= -DPXE_HTTP_DEBUG +#CFLAGS+= -DPXE_HTTP_DEBUG_HELL + +# define to get more PXE related code and testing functions +#CFLAGS+= -DPXE_MORE + +# define to get some speed up by bigger requests +CFLAGS+= -DPXE_HTTPFS_CACHING + +# define to send packets freqently to speed up connection +#CFLAGS+= -DPXE_TCP_AGRESSIVE + +# define to automatically choose non keep-alive method of +# working, if keep-alive is not supported by server +CFLAGS+= -DPXE_HTTP_AUTO_KEEPALIVE + +.include <bsd.lib.mk> Added: user/sbruno/pxestuff/sys/boot/i386/pxehttp/README ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/sbruno/pxestuff/sys/boot/i386/pxehttp/README Wed Jan 16 01:49:07 2013 (r245486) @@ -0,0 +1,1256 @@ +Contents +---------- + +1. Introduction + + 1.2. Setting up + + 1.2.1. DHCP configuration + 1.2.2. TFTP configuration + 1.2.3. Web-server configuration + 1.2.4. loader.rc configuratuion + +2. Project organisation + + 2.1. Code modules + 2.2. Naming conventions + 2.3. Understanding logical structure of code + +3. API usage + + 3.1. Base information + 3.2. PXE sockets API overview + + 3.2.1. PXE API socket details + + 3.3. Quick Reference to API, available for user code + + 3.3.1. pxe_arp module + 3.3.2. pxe_await module + 3.3.3. pxe_buffer module + 3.3.4. pxe_connection module + 3.3.5. pxe_core module + 3.3.6. pxe_dhcp module + 3.3.7. pxe_dns module + 3.3.8. pxe_filter module + 3.3.9. pxe_http module + 3.3.10. httpfs module + 3.3.11. pxe_icmp module + 3.3.12. pxe_ip module + 3.3.13. pxe_isr module + 3.3.14. pxe_mem module + 3.3.15. pxe_sock module + 3.3.16. pxe_segment module + 3.3.17. pxe_tcp module + 3.3.18. pxe_udp module + +4. Debugging, testing and tuning pxe_http library. + + 4.1. Using 'pxe' loader's command + 4.2. Defining debug macroses + 4.3. Tuning + 4.4. NFS loading with pxe_http + +1. Introduction +---------------- + + pxe_http library is user space implementation of simplified + TCP/IP4 stack with support of sockets. Socket implementation is similar + to common sockets, but differs, so I call this variant of sockets - + "PXE sockets" + + features (read: simpliest ever implementation of): + * supports TCP/UDP PXE sockets + * DHCP client + * DNS client + * http based filesystem + * ICMP echo + +1.1. Requirements +------------------ + + To use pxeboot with extensions from pxe_http library + you need: + * DHCP server + - any DHCP server with support of some options + (see below). In example of configuration files + ISC DHCP v.3.0.5 was used. + * TFTP server + * Web server - I've used Apache 1.3.34 + + +1.2. Setting it up +------------------- + + In most cases, it's the same as for usual pxeboot. Main + difference is in configuration file of DHCP server and in usage of + Web-server. + + +1.2.1. DHCP configuration +------------------------- + + Here is example of configuration: + + # /etc/dhcpd.conf example + # + ddns-update-style none; + server-name "DHCPserver"; + server-identifier 192.168.0.4; + default-lease-time 7200; + max-lease-time 7200; + + # + # significant options for correct working of pxeboot + # + + # your LAN subnet mask + option subnet-mask 255.255.255.0; + + # default gateway to use + option routers 192.168.0.1; + + # name of file to download via TFTP + filename "pxeboot"; + + # name server, used for resolving of domain names + option domain-name-servers 192.168.0.1; + + # ip address of web server + option www-server 192.168.0.2; + + # path, where nessesary files are stored on web server + option root-path "th.lan:/path/to/root"; + + subnet 192.168.0.0 netmask 255.255.255.0 { + next-server 192.168.0.4; + range 192.168.0.10 192.168.0.20; + } + + /* end of example */ + + NOTES: + 1. www-server option is used only if root-path is absent in + DHCP reply. In that case assumed, that /boot directory is + placed in DocumentRoot of web-server. + 2. format of root-path has such format: "server:/path". It's + possible use both IP's and domain names for server. /path is + relative to DocumentRoot of web-server. In example above + files are stored at /usr/local/www/data/path/to/root, + assuming that /usr/local/www/data - is DocumentRoot. + 3. DHCP options are not greater then 255 bytes. So, root-path + must satisfy this requirement. + + +1.2.2. TFTP configuration +-------------------------- + + Same as usually. pxe_http doesn't directly use this protocol. + + +1.2.3. Web-server configuration +-------------------------------- + + Just copy all from "/boot" directory to + /DocumentRoot/path/to/root. + + NOTES: + 1. Need to be sure, that partial downloading and keep-alive + connections are supported by server. e.g. for Apache 1.x, + check this options: + + KeepAlive On + MaxKeepAliveRequests 10 # well, choose best for + # server + KeepAliveTimeout 15 # more then 2 seconds + # is good enough + + 1.1 Non keep-alive connections supported if macro + PXE_HTTP_AUTO_KEEPALIVE defined. In this case, non keep-alive + connections will be used if keep-alive are unavailable. + + 2. loader checks gzipped versions of files first, it's good + idea to compress every needed file. e.g. + beastie.4th.gz + device.hints + frames.4th.gz + loader.4th.gz + loader.conf + loader.help.gz + loader.rc + mfsroot.gz + screen.4th.gz + support.4th.gz + /kernel/kernel.gz + +1.2.4. loader.rc configuratuion +-------------------------------- + + HTTP downloading of kernel is not all need to startup system + correctly. The main question is where will be root filesystem after + booting of kernel. The simpliest way - is to use RAM drive with + installation tools or ready to work system. + Here is example of changes to loader.rc, that instructs loader + to download RAM-drive image (in this example, common mfsroot.gz found + in boot.flp floppy image file) + + + \ Includes additional commands + include /boot/loader.4th + + \ Reads and processes loader.conf variables + start + + \ Tests for password -- executes autoboot first if a password was defined + check-password + + \ Load in the boot menu + include /boot/beastie.4th + + \ pxe_http changes: + echo "loading RAM-drive image" + load -t mfs_root /boot/mfsroot + set vfs.root.mountfrom="ufs:/dev/md0c" + \ + + \ Start the boot menu + beastie-start + + /* end of example */ + + Of course, it's possible to set any other filesystem to work + as root, e,g, NFS and not use RAM drive. + +2. Project organisation +------------------------ + +2.1. Code modules +------------------ + + All project code is divided into following modules: + pxe_arp - ARP protocol (3.3.1) + pxe_await - provides functions for awaiting (3.3.2) + pxe_buffer - implements cyclic buffers (3.3.3) + pxe_connection - TCP connection related functions (3.3.4) + pxe_core - provides calls to PXE API (3.3.5) + pxe_dhcp - DHCP client (3.3.6) + pxe_dns - DNS client (3.3.7) + pxe_filter - incoming packet filters (3.3.8) + pxe_http - HTTP related functions (3.3.9) + httpfs - http based file system (3.3.10) + pxe_icmp - ICMP protocol (3.3.11) + pxe_ip - IP protocol (3.3.12) + pxe_isr - assembler side support for PXE API + calling (3.3.13) + pxe_mem - memory work routines (3.3.14) + pxe_sock - simple sockets (3.3.15) + pxe_segment - TCP segments (3.3.16) + pxe_tcp - TCP protocol (3.3.17) + pxe_udp - UDP protocol (3.3.18) + +2.2. Naming conventions +------------------------ + + Most of functions, that may be called directly by user API uses + pxe_ prefix. + Functions related to some module have subprefix of this module, + e.g. pxe_dhcp_query() - function related to DHCP module. + All structures, that are used have typedef equivalent with + naming in upper case. e.g. struct pxe_ipaddr has equivalent PXE_IPADDR. + This is done to have similar to existing pxe.h declarations from libi386. + + +2.3. Understanding logical structure of code +--------------------------------------------- + + Logicallly all modules may be divided to parts. + + Part 1: PXE API related modules (pxe_isr, pxe_core) + Part 2: base protocols related (pxe_ip, pxe_udp) + Part 3: sockets related (pxe_sock) + Part 4: other protocols (pxe_dns, pxe_dhcp) + Part 5: utility (pxe_mem, pxe_buffer) + + Some modules may be used independently, other depend on some + lower level modules. + + In run-time, many calls to sockets functions start packet + recieving or packet sending functions. Sending is more simplier and may + be assumed in many cases just as wrappers to PXE API. But receiving is + a little bit more complicated. Receiving functions start + pxe_core_recv_packets() function in cycle to get packets. + After receiving of packet, it's handling depends on it's type: + ARP, IP or other. ARP packets directly provided to handler + pxe_arp_protocol(), IP packets are provided to registered handler of IP + stack protocol, other packets are ignored. + Registration of handler (except ARP) is performed during + initialisation time of module with usage of pxe_core_register() function, + which register handler for IP stack protocol number. + So, packet is provided to handler, but it may be fragmented, + thus before processing it must be recieved completely. But in some cases + packet may be not interesting for protocol (unexpected packet, dublicated + or something else) and it's possible to determiny if this packet useful + just by examining of packet header. + If packet is fragmented - it firstly provided to handler with + flag PXE_CORE_FRAG. Handler returns appropriate value if is interested in + whole packet, packet is read completely from input queue of fragments and + provided again with flag PXE_CORE_HANDLE. Otherwise packet is dropped + in core by reading of all it's fragments from incoming queue. + Packet structure provides just buffer with received packet and + size of packet. All pxe_core module send/recieve functions work with + PXE_PACKET structure. + TCP and UDP protocols are checking filters in theirs handlers. + This helps to filter out packets that are not interesting for protocol + (e.g. to port that is not listening) + Socket and filter structures are separated. Socket provides + buffers for incoming and outcoming data. Filters may be used without + sockets, e.g. for TCP connections in TIME_WAIT state. For active + connection filter is used to determiny in which receiving buffer (in + which socket) must be placed incoming data. + + +3. API usage +------------- + + Here much attention paid to sockets, other pxe_http API + may be used less frequently. + +3.1. Base information +----------------------- + + User code must perform initialisation of pxe_core module (which + is performed currently in loader during pxe_enable() call). After this + sockets related functions become available. + + pxe_core_init() performs initialisation of pxe_core module and starts + initialisation routines of other modules. It inits TCP, UDP, ARP and + etc modules, however in most of cases it's possible skip theirs + initialisation if module's functions are unused. + Work is finished by pxe_core_shutdown() function. + + +3.2. PXE sockets API overview +------------------------------- + + PXE sockets API differs from common sockets. It's more simplier + and has some limitations due user space implementations. All socket + related functions are declared in pxe_sock.h header + + Socket is created by pxe_socket() call. After usage socket must + be closed by pxe_close() call. Result of pxe_socket() is integer + descriptor associated with socket. After creating socket is unbinded + and not connected. + pxe_sendto(), pxe_connect(), pxe_bind() functions performs + binding and connecting. After successful calling of one of them - socket + is in active state. It's possible to perform reading and sending from/to + socket. Cause socket API may use buffers to optimize packet sending + process, user code must call pxe_flush() functions to be sure, that + data is really processed to sending module. + While receiving need to keep in memory, that if UDP datagram is + not readed completely by one call of pxe_recv() in this implementation + rest of datagram is omited and lost for user code. + All incoming and outcoming data is written to socket buffers, + that have default sizes 16Kb and 4Kb. If buffers are full, next calls + related to writing or reading data will fail. + + +3.2.1. PXE API socket details +------------------------------ + + /* Here is simple example of API usage. */ + + int socket = pxe_socket(); + /* if result is not -1, then socket variable contains value, + * assosiated with socket structure. Call differs from common sockets, + * there are no domain, type and protocol parameters. + * Cause domain is always AF_INET now. others are use in pxe_connect() + * call. + */ + + int result = pxe_connect(socket, &hh->addr, 80, PXE_TCP_PROTOCOL); + /* This call creates filter, associates it with socket and establishes + * communication if needed. + * Parameters are socket, remote ip address (PXE_IPADDR), remote port + * and one of PXE_UDP_PROTOCOL and PXE_TCP_PROTOCOL protocols. + */ + + if (result == -1) { + pxe_close(socket); + /* any socket must be closed, even if it was not really used + * or conencted. pxe_close() call releases used internal + * structures. After this call any other operations with + * 'socket' descriptor are invalid. + */ + return (0); + } + + /* pxe_send() function sends data to socket. As usual, there is no + * guarantee, that whole buffer is transmited. And actually for TCP + * protocol, this call just places data to buffer. User code have no + * knowledge if data is really sent to network. if current segment is + * not fullly used, data may stay in buffer infinitely. + */ + if (len != pxe_send(socket, hh->buf, len)) { + /* failed to send data, at least whole buffer */ + pxe_close(socket); + return (0); + } + + /* if user code need guarantee, that data is sent to remote host, it + * must call pxe_flush(). It forces sending of any data, that must be + * sent. + */ + if (pxe_flush(socket) == -1) { + /* failed to flush socket */ + pxe_close(socket); + return (0); + } + + /* perform reading cycle */ + + while (count < maxsize) { + /* pxe_recv() is similar to recv() call for common sockets, + * but have no flags parameter + */ + result = pxe_recv(socket, &data[count], maxsize - count); + + if (result == -1) { /* failed to recv */ + break; + } + + if (result == 0) /* nothing received yet */ + continue; + + count += result; + } + + pxe_close(socket); + + + /* End of example */ + + +3.3 Quick Reference to API, available for user code +---------------------------------------------------- + + This overview covers functions and macro definitions that + may be usefull for user code. + + +3.3.1 pxe_arp module +--------------------- + + This module is used mainly by internal code while sending IP + packets. + +macro definitions: + +MAX_ARP_ENTRIES - how much may be ARP table in size. If ARP table full + and new MAC must be placed, then one of older entry is + replaced by new. Default number is 4. + +PXE_MAX_ARP_TRY - how much trys will be peformed when sending ARP + requests, before say MAC search failed. Default: 3 + +PXE_TIME_TO_DIE - how much time to wait ARP reply in milliseconds. + Default: 5000 ms. + +PXE_ARP_SNIFF - sometimes it's usefull to get senders MACs from + incoming requests (this may save time, MAC may be found + in table without requesting it by ARP module itself). + But if network is big enough - ARP table will be + updated too often. By default this option is defined. + + +functions: + +void pxe_arp_init() + - inits pxe_arp module. Usually this call is performed from + pxe_core_init() + +const MAC_ADDR *pxe_arp_ip4mac(const PXE_IPADDR *addr) + - returns MAC address for requested IP address + +void pxe_arp_stats() + - shows ARP table. Available if defined PXE_MORE macro. + + +3.3.2 pxe_await module +----------------------- + + Implements awaiting mechanism. Many operations are performed + similar in protocol implementations. Usually, packet is sended and + application awaits for reply. pxe_await() function helps to simplify + code in such case. + It starts await callback function with some flags and counts + timeouts, try count. + + Here is example of awaiting: + + /* we start awaiting, with dns_await() calllback function, maximum 4 + * trys, each try 20 seconds and waiting data static_wait_data. + * Waiting data - is some data associated with current awaiting, it's + * used by await callback function. + */ + if (!pxe_await(dns_await, 4, 20000, &static_wait_data)) + return (NULL); + + /* pxe_await() returns 1 if awaiting was successfull (await function + * returned PXE_AWAIT_COMPLETED flag) + */ + + /* it's an awaiting function. pxe_await() provides current function, + * current try number, time exceeded from start of try, pointer to + * associated wait data. + */ + int + dns_await(uint8_t function, uint16_t try_number, uint32_t timeout, + void *data) + { + /* cast to our type of wait data */ + PXE_DNS_WAIT_DATA *wait_data = (PXE_DNS_WAIT_DATA *)data; + + switch(function) { + + case PXE_AWAIT_STARTTRY: + /* is called at start of each try + * Here must be performed any await initialisation + * (e.g. request packet sending ) + */ + if (!dns_request(wait_data)) { + /* if initialisation of try failed, try more */ + return (PXE_AWAIT_NEXTTRY); + } + /* otherwise return success result of await function */ + break; + + case PXE_AWAIT_FINISHTRY: + /* this function is called at the end of any try (even + * if try was successful). Here cleanup must be + * performed. + */ + if (wait_data->socket != -1) + pxe_close(wait_data->socket); + + wait_data->id += 1; + break; + + case PXE_AWAIT_NEWPACKETS: + /* while waiting this function called if new packets + * were received by pxe_core_recv_packets(). Actually + * it may be not packets we are waiting for, may be + * even not packets with out protocol. Here we must + * check for new usefull for us packets, receive + * new data if any. + */ + size = pxe_recv(wait_data->socket, wait_data->data, + wait_data->size); + + parse_dns_reply(wait_data); + + if (wait_data->result.ip != 0) { + /* return success of awaiting. This may be + * returned from any function + */ + return (PXE_AWAIT_COMPLETED); + } + + /* if await was not completed, continue waiting */ + return (PXE_AWAIT_CONTINUE); + break; + + case PXE_AWAIT_END: + /* this called if await is ended without any result */ + default: + break; + } + + return (PXE_AWAIT_OK); + } + + /* end of example */ + + So, wait data used for providing and receiving data while + awaiting. pxe_await() performs unified working with code, needed for + waiting of incoming packets. + +macro definitions: + +TIME_DELTA_MS - delay between iterations during awaitng. At each + iteration are checked: + * receiving of new packet. If received - awaiting + function with PXE_AWAIT_NEWPACKETS function is called. + * try timeout. if timeout exceeds maximum timeout - + awaiting function with PXE_AWAIT_FINISHTRY and + PXE_AWAIT_STARTTRY flags sequentially are called. + * try count. if try count exceeds maximum - awaiting + function with PXE_AWAIT_ENDED flag is called. This + means that await failed. + Default: 1 + +TIME_DELTA - default: 1000, same as TIME_DELTA_MS, but in ticks + for delay. + + +3.3.3 pxe_buffer module +------------------------ + + This module provides reading and writing of cyclic buffers. + It's not used directly by user code. + +macro definitions: + +PXE_POOL_SLOTS - if defined, then statical allocation of buffers is + used. Otherwise buffers are allocated at run-time from + heap with pxe_alloc() function. Current statical + allocation algorithm is simple and square, there are + two big buffers data storages divided in slots (by + default 2). + Each slot has size equal to + PXE_DEFAULT_RECV_BUFSIZE or PXE_DEFAULT_SEND_BUFSIZE. + Depending on requested size in pxe_buffer_alloc() + function data allocated from one of stoarge and + related slot marked busy. When pxe_buffer_free() called, + slot marked as free. + Default: undefined + +PXE_DEFAULT_RECV_BUFSIZE - size of receiving buffer. Default: 16392 + +PXE_DEFAULT_SEND_BUFSIZE - size of sending buffer. Default: 4096 + + +3.3.4 pxe_connection module +---------------------------- + + This module is one of TCP related modules. It implements + connection entity. TCP connection is logical structure, that have + needed by TCP protocol counters and states. + User code is not directly works with this module. + +macro definitions: + +PXE_MAX_TCP_CONNECTIONS - how much simultaneous connections may be. + + +functions: + +void pxe_connection_stats() + - returns connections statistics. Available if PXE_MORE macro is + defined. + + +3.3.5 pxe_core module +---------------------- + + This module performs lowlevel work with PXE API: initialisation, + receiving/sending of packets, provides information functions. + In most cases, user code doesn't uses this module directly. + +macro definitions: + +PXE_BUFFER_SIZE - size of core buffers, used in PXE API calling, + Default: 4096 + +PXE_CORE_STATIC_BUFFERS - if defined, core buffers are allocated statically. + Otherwise they are allocated in heap. Default: defined + +functions: + +int pxe_core_recv_packets() + - recieves all packets waiting in incoming queue of NIC, and calls + appropriate protocols if needed + + +void pxe_core_register(uint8_t ip_proto, pxe_protocol_call proc) + - registers IP stack protocol, associates protocol number and handler. + +const MAC_ADDR *pxe_get_mymac() + - returns MAC of NIC, for which PXE API is used. + +const PXE_IPADDR *pxe_get_ip(uint8_t id) + - returns of stored IP, for provided id. + id may be: + PXE_IP_MY - NIC IP address + PXE_IP_NET - network adrress + PXE_IP_NETMASK - network mask + PXE_IP_NAMESERVER - nameserver to use in name resolving + PXE_IP_GATEWAY - default gateway + PXE_IP_BROADCAST - broadcast address + PXE_IP_SERVER - server from which loading of pxeboot + was performed + PXE_IP_WWW - IP address of http-server + PXE_IP_ROOT - IP adddress of server, where root + file system is situated. + +void pxe_set_ip(uint8_t id, const PXE_IPADDR *ip) + - sets value by it's id. + +time_t pxe_get_secs() + - returns time in seconds. Used in timeout and resend checking. + +types: + +typedef int (*pxe_protocol_call)(PXE_PACKET *pack, uint8_t function) + - protocol callback function type + + +3.3.6. pxe_dhcp module +----------------------- + + This module implements simple DHCP client, used to obtain + gateway, nameserver and other information. + + +macro definitions: + +PXE_BOOTP_USE_LIBSTAND - use bootp() function provided by libstand instead + of own DHCP client. NOTE: bootp() doesn't set nameip (nameserver ip + structure), thus DNS resolving will be impossible. Default: undefined + + NOTE: to use bootp(), also UDP_DEFAULT_SOCKET macro must be defined. + + +functions: + +void pxe_dhcp_query(uint32_t xid) + - sends DHCPDISCOVER packet and sets core_ips, if gets reply. + + +3.3.6. pxe_dns module +---------------------- + + This module provides domain name resolving. Actually + A and CNAME resource records are supported. + +macro definitions: + +PXE_MAX_DNS_TIMEOUT - max time to wait DNS reply in milliseconds. + Default: 10 seconds + +PXE_MAX_DNS_TRYS - how many times to try to resend request, + if there is no reply. Default: 3 + +PXE_DNS_MAX_PACKET_SIZE - maximum UDP packet size in bytes. Default: 512. + This DNS client doesn't support TCP for resolving. + +functions: + +const PXE_IPADDR *pxe_gethostbyname(char *name) + - returns IP, if resolved, for provided domain name. + +uint32_t pxe_convert_ipstr(char *str) + - converts string value of ipv4 to uint32_t value. + + +3.3.8. pxe_filter module +------------------------- + + This module is not supposed to be used by user code directly. + It implements filtering of incoming IP packets. It's used by UDP and + TCP modules for sorting packets in appropriate socket. + Module provides functions for adding and removing filters. + Each filter contains source/destination ip:port definition and masks + for all of them. Usage of masks gives opportunity to recieve data + from subnet, or subset of ports. + +functions: + +void pxe_filter_init() + - inits filter module structures such as list of free filter entries. + +void pxe_filter_stats() + - show active filters information. Used for debugging. Available if + PXE_MORE macro defined. + + *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201301160149.r0G1n8Wl026588>