svn commit: r245486 - in user/sbruno/pxestuff/sys/boot/i386: . btx/btx btx/lib libi386 pxehttp
Sean Bruno
sbruno at FreeBSD.org
Wed Jan 16 01:49:09 UTC 2013
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 ***
More information about the svn-src-user
mailing list