summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2012-10-11 21:16:37 +0100
committerMatt Fleming <matt.fleming@intel.com>2012-10-11 21:17:58 +0100
commit940d4876ab8dc6dcbdbf47ba8be98cba0516c66e (patch)
treeb42256b0f3344a52622febf3306933ae1f8bd864
parent7d9ee65cc9577eb69782a49a34895ae80820e9ff (diff)
parent85dba2c3058996d72def4a44304df882da3aa807 (diff)
downloadsyslinux-940d4876ab8dc6dcbdbf47ba8be98cba0516c66e.tar.gz
Merge branch 'pxechn-fix-news-for-hpa-2' of git://github.com/geneC/syslinux
Conflicts: NEWS com32/modules/Makefile
-rw-r--r--NEWS4
-rw-r--r--com32/modules/Makefile2
-rw-r--r--com32/modules/prdhcp.c164
-rw-r--r--com32/modules/pxechn.c49
-rw-r--r--doc/pxechn.txt106
5 files changed, 287 insertions, 38 deletions
diff --git a/NEWS b/NEWS
index f19e0d5d..20a22791 100644
--- a/NEWS
+++ b/NEWS
@@ -16,7 +16,9 @@ Changes in 4.06:
functions syslinux_config(), syslinux_ipappend_strings() and
syslinux_reboot().
* isohybrid: Workaround for various EFI systems.
- * pxechn.c32: New PXE NBP chainloader.
+ * pxechn.c32, a PXE NBP chainloader. More versatile alternative
+ to pxechain.com and resolves the PXELINUX -> WDS issue with
+ Microsoft Windows Server 2008R2 (Gene Cumm).
* btrfs: Fix booting off of a subvolume.
* com32: Add device tree support.
diff --git a/com32/modules/Makefile b/com32/modules/Makefile
index 24b7d283..f110e584 100644
--- a/com32/modules/Makefile
+++ b/com32/modules/Makefile
@@ -24,7 +24,7 @@ MODULES = config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \
meminfo.c32 sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 \
kbdmap.c32 cmd.c32 vpdtest.c32 host.c32 ls.c32 gpxecmd.c32 \
ifcpu.c32 cpuid.c32 cat.c32 pwd.c32 ifplop.c32 zzjson.c32 \
- whichsys.c32 pxechn.c32 kontron_wdt.c32 ifmemdsk.c32
+ whichsys.c32 prdhcp.c32 pxechn.c32 kontron_wdt.c32 ifmemdsk.c32
TESTFILES =
diff --git a/com32/modules/prdhcp.c b/com32/modules/prdhcp.c
new file mode 100644
index 00000000..321d4e77
--- /dev/null
+++ b/com32/modules/prdhcp.c
@@ -0,0 +1,164 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2010-2011 Gene Cumm - All Rights Reserved
+ *
+ * Portions from chain.c:
+ * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ * Significant portions copyright (C) 2010 Shao Miller
+ * [partition iteration, GPT, "fs"]
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * prdhcp.c
+ *
+ * Print the contents of the 3 DHCP packets
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <consoles.h>
+#include <console.h>
+#include <errno.h>
+#include <string.h>
+#include <syslinux/config.h>
+#include <syslinux/loadfile.h>
+#include <syslinux/bootrm.h>
+#include <syslinux/video.h>
+#include <com32.h>
+#include <stdint.h>
+#include <syslinux/pxe.h>
+#include <sys/gpxe.h>
+#include <unistd.h>
+#include <getkey.h>
+
+#define DEBUG 1
+
+#define dprintf0(f, ...) ((void)0)
+
+#ifdef DEBUG
+# define dpressanykey pressanykey
+# define dprintf printf
+# define dprint_pxe_bootp_t print_pxe_bootp_t
+# define dprint_pxe_vendor_blk print_pxe_vendor_blk
+# define dprint_pxe_vendor_raw print_pxe_vendor_raw
+#else
+# define dpressanykey(void) ((void)0)
+# define dprintf(f, ...) ((void)0)
+# define dprint_pxe_bootp_t(p, l) ((void)0)
+# define dprint_pxe_vendor_blk(p, l) ((void)0)
+# define dprint_pxe_vendor_raw(p, l) ((void)0)
+#endif
+
+#define dprintf_opt_cp dprintf0
+#define dprintf_opt_inj dprintf
+
+
+const char app_name_str[] = "prdhcp.c32";
+
+
+int pressanykey(void) {
+ int inc;
+
+ printf("Press any key to continue. ");
+ inc = KEY_NONE;
+ while (inc == KEY_NONE)
+ inc = get_key(stdin, 6000);
+ puts("");
+ return inc;
+}
+
+void print_pxe_vendor_blk(pxe_bootp_t *p, size_t len)
+{
+ int i, vlen, oplen, j;
+ uint8_t *d;
+ uint32_t magic;
+ if (!p) {
+ printf(" packet pointer is null\n");
+ return;
+ }
+ vlen = len - ((void *)&(p->vendor) - (void *)p);
+ printf(" Vendor Data: Len=%d", vlen);
+ d = p->vendor.d;
+ /* Print only 256 characters of the vendor/option data */
+ /*
+ print_pxe_vendor_raw(p, (len - vlen) + 256);
+ vlen = 0;
+ */
+ magic = ntohl(*((uint32_t *)d));
+ printf(" Magic: %08X", ntohl(*((uint32_t *)d)));
+ if (magic != VM_RFC1048) /* Invalid DHCP packet */
+ vlen = 0;
+ for (i = 4; i < vlen; i++) {
+ if (d[i]) /* Skip the padding */
+ printf("\n @%03X-%3d", i, d[i]);
+ if (d[i] == 255) /* End of list */
+ break;
+ if (d[i]) {
+ oplen = d[++i];
+ printf(" l=%3d:", oplen);
+ for (j = (++i + oplen); i < vlen && i < j; i++) {
+ printf(" %02X", d[i]);
+ }
+ i--;
+ }
+ }
+ printf("\n");
+}
+
+void print_pxe_bootp_t(pxe_bootp_t *p, size_t len)
+{
+ if (!p) {
+ printf(" packet pointer is null\n");
+ return;
+ }
+ printf(" op:%02X hw:%02X hl:%02X gh:%02X id:%08X se:%04X f:%04X"
+ " cip:%08X\n", p->opcode, p->Hardware, p->Hardlen, p->Gatehops,
+ ntohl(p->ident), ntohs(p->seconds), ntohs(p->Flags), ntohl(p->cip));
+ printf(" yip:%08X sip:%08X gip:%08X",
+ ntohl(p->yip), ntohl(p->sip), ntohl(p->gip));
+ printf(" caddr-%02X:%02X:%02X:%02X:%02X:%02X\n", p->CAddr[0],
+ p->CAddr[1], p->CAddr[2], p->CAddr[3], p->CAddr[4], p->CAddr[5]);
+ printf(" sName: '%s'\n", p->Sname);
+ printf(" bootfile: '%s'\n", p->bootfile);
+ print_pxe_vendor_blk(p, len);
+}
+
+void print_dhcp_pkt_all(void)
+{
+ pxe_bootp_t *p;
+ size_t len;
+ int i;
+ int ptype[3] = {PXENV_PACKET_TYPE_DHCP_DISCOVER, PXENV_PACKET_TYPE_DHCP_ACK, PXENV_PACKET_TYPE_CACHED_REPLY};
+
+ for (i = 0; i < 3; i++) {
+ if (!pxe_get_cached_info(ptype[i],
+ (void **)&(p), &(len))) {
+ dprintf("Got packet #%d/%d\n", (i + 1), ptype[i]);
+ print_pxe_bootp_t(p, len);
+ pressanykey();
+ }
+ }
+}
+
+int main(void)
+{
+ int rv= -1;
+ const struct syslinux_version *sv;
+
+ console_ansi_raw();
+ sv = syslinux_version();
+ if (sv->filesystem != SYSLINUX_FS_PXELINUX) {
+ printf("%s: May only run in PXELINUX\n", app_name_str);
+ return -2;
+ }
+ print_dhcp_pkt_all();
+ return rv;
+}
diff --git a/com32/modules/pxechn.c b/com32/modules/pxechn.c
index 3f9ebd32..26376900 100644
--- a/com32/modules/pxechn.c
+++ b/com32/modules/pxechn.c
@@ -43,7 +43,11 @@
#include <limits.h>
-#define PXECHN_DEBUG 1
+#ifdef DEBUG
+# define PXECHN_DEBUG 1
+#else
+# define PXECHN_DEBUG 0
+#endif
typedef union {
uint64_t q;
@@ -54,15 +58,21 @@ typedef union {
#define dprintf0(f, ...) ((void)0)
+#ifndef dprintf
+# if (PXECHN_DEBUG > 0)
+# define dprintf printf
+# else
+# define dprintf(f, ...) ((void)0)
+# endif
+#endif
+
#if (PXECHN_DEBUG > 0)
# define dpressanykey pressanykey
-# define dprintf printf
# define dprint_pxe_bootp_t print_pxe_bootp_t
# define dprint_pxe_vendor_blk print_pxe_vendor_blk
# define dprint_pxe_vendor_raw print_pxe_vendor_raw
#else
# define dpressanykey(tm) ((void)0)
-# define dprintf(f, ...) ((void)0)
# define dprint_pxe_bootp_t(p, l) ((void)0)
# define dprint_pxe_vendor_blk(p, l) ((void)0)
# define dprint_pxe_vendor_raw(p, l) ((void)0)
@@ -107,6 +117,7 @@ struct pxelinux_opt {
uint32_t force;
uint32_t wait; /* Additional decision to wait before boot */
int32_t wds; /* WDS option/level */
+ in_addr_t sip; /* siaddr: Next Server IP Address */
struct dhcp_option p[PXECHN_NUM_PKT_AVAIL];
/* original _DHCP_DISCOVER, _DHCP_ACK, _CACHED_REPLY then modified packets */
char host[PXECHN_HOST_LEN];
@@ -453,6 +464,7 @@ void pxechn_init(struct pxelinux_opt *pxe)
pxe->wait = 0;
pxe->gip = 0;
pxe->wds = 0;
+ pxe->sip = 0;
pxe->host[0] = 0;
pxe->host[((NUM_DHCP_OPTS) - 1)] = 0;
for (int j = 0; j < PXECHN_NUM_PKT_TYPE; j++){
@@ -731,7 +743,7 @@ int pxechn_parse_args(int argc, char *argv[], struct pxelinux_opt *pxe,
{
int arg, optnum, rv = 0;
char *p = NULL;
- const char optstr[] = "c:f:g:o:p:t:uwW";
+ const char optstr[] = "c:f:g:o:p:St:uwW";
struct dhcp_option iopt;
if (pxe->p[5].data)
@@ -765,6 +777,9 @@ int pxechn_parse_args(int argc, char *argv[], struct pxelinux_opt *pxe,
case 'p': /* prefix */
pxechn_setopt_str(&(opts[210]), optarg);
break;
+ case 'S': /* sip from sName */
+ pxe->sip = 1;
+ break;
case 't': /* timeout */
optnum = strtoul(optarg, &p, 0);
if (p != optarg) {
@@ -809,6 +824,7 @@ int pxechn_args(int argc, char *argv[], struct pxelinux_opt *pxe)
pxe_bootp_t *bootp0, *bootp1;
int ret = 0;
struct dhcp_option *opts;
+ char *str;
opts = pxe->opts[2];
/* Start filling packet #1 */
@@ -826,7 +842,30 @@ int pxechn_args(int argc, char *argv[], struct pxelinux_opt *pxe)
ret = pxechn_parse_args(argc, argv, pxe, opts);
if (ret)
return ret;
- bootp1->sip = pxe->fip;
+ if (pxe->sip > 0xFFFFFF) { /* a real IPv4 address */
+ bootp1->sip = pxe->sip;
+ } else if ((pxe->sip == 1)
+ && (opts[66].len > 0)){
+ /* unterminated? */
+ if (strnlen(opts[66].data, opts[66].len) == (size_t)opts[66].len) {
+ str = malloc(opts[66].len + 1);
+ if (str) {
+ memcpy(str, opts[66].data, opts[66].len);
+ str[opts[66].len] = 0;
+ }
+ } else {
+ str = opts[66].data;
+ }
+ if (str) {
+ bootp1->sip = pxe_dns(str);
+ if (str != opts[66].data)
+ free(str);
+ } else {
+ bootp1->sip = pxe->fip;
+ }
+ } else {
+ bootp1->sip = pxe->fip;
+ }
bootp1->gip = pxe->gip;
ret = dhcp_pack_packet(bootp1, (size_t *)&(pxe->p[5].len), opts);
diff --git a/doc/pxechn.txt b/doc/pxechn.txt
index a09bbe2b..7853d9ab 100644
--- a/doc/pxechn.txt
+++ b/doc/pxechn.txt
@@ -1,88 +1,131 @@
-= pxechn.c32 =
+= pxechn.c32(1) =
:doctype: manpage
:author: Gene Cumm
:email: gene.cumm@gmail.com
-:revdate: 2012-05-27
+:revdate: 2012-09-16
== NAME ==
-pxechn.c32 - Chainboot to new NBP
+pxechn.c32 - Chainboot to new Network Boot Program (NBP)
== SYNOPSIS ==
+[verse]
*pxechn.c32* [-h | --help | -?]
*pxechn.c32* -r 'FILE'
*pxechn.c32* 'FILE' ['OPTIONS']
== DESCRIPTION ==
-Chainboot to a new NBP (Network Boot Program) 'FILE' with options to adjust PXE packet #3 (PXENV_PACKET_TYPE_CACHED_REPLY) to alter end behavior. 'FILE' may be a filename, an IP::FN ( 192.168.1.1::path/to/file.0 ), or URL. 'FILE' is parsed to adjust the DHCP 'sname' field/option 66 and 'file' field/option 67.
+Chainboot to a new Network Boot Program (NBP) 'FILE' with options to
+adjust PXE packet #3 (PXENV_PACKET_TYPE_CACHED_REPLY) to alter end
+behavior. 'FILE' may be a filename, an IP::FN (
+192.168.1.1::path/to/file.0 ), or URL. 'FILE' is parsed to adjust the
+DHCP 'sname' field/option 66 and 'file' field/option 67.
// but these may be override-able in the future.
== OPTIONS ==
*-c* 'CONFIG'::
- PXELINUX config file (DHCP Option 209).
+ 'config' file for PXELINUX (DHCP Option 209).
// *-f* 'MOD'::
-// Force behavior specified by 'MOD'
+// 'Force' behavior specified by modifier 'MOD'
//
// *-g* 'HOST'::
-// Set DHCP gateway/relay. Parsed by pxe_dns().
+// Set 'gateway'/relay DHCP field to 'HOST'. Parsed by pxe_dns().
//
*-h*, *--help*, *-?*::
- Print usage information; invalid options will also cause this.
+ Print 'help'/usage information; invalid options will also cause
+ this.
// *-n*::
-// Use native methods, ignoring underlying gPXE/iPXE.
+// Use 'native' methods, ignoring underlying gPXE/iPXE.
//
// *-N*::
-// Use non-native methods to utilize gPXE/iPXE (if available).
+// Use 'non-native' methods to utilize gPXE/iPXE (if available).
//
*-o* 'OPT.TYPE=VALUE'::
- Specify a generic option. 'OPT' is in 'DECIMAL INPUT' format (below). 'TYPE' specifies the output type and input syntax. 'b'yte, 'w'ord(2B), 'l'ong(4B), 'q'uad(8B), character 's'tring and colon-separated he'x' string (case insensitive; bytes must have 2 digits and each byte must be separated). byte, word, long and quad input values must meet criteria for 'DECIMAL INPUT'
+ Set 'option'. 'OPT' is in 'DECIMAL INPUT' format (below). 'TYPE'
+ specifies the output type and input syntax (listed here in quotes
+ and at present, 1 character). ''b'yte', ''w'ord'(2B), ''l'ong'(4B),
+ ''q'uad'(8B), character ''s'tring' and colon-separated 'he'x''
+ string (case insensitive; bytes must have 2 digits and each byte
+ must be separated). byte, word, long and quad input values must
+ meet criteria for 'DECIMAL INPUT'
*-p* 'PATH'::
- PXELINUX path (DHCP Option 210).
+ 'path' option for PXELINUX (DHCP Option 210).
*-r*::
- Call the PXE stack with PXENV_RESTART_TFTP. _Must_ be the only option and before 'FILE'.
+ 'restart'. Call the PXE stack with PXENV_RESTART_TFTP. _Must_ be
+ the only option and before 'FILE'.
+
+*-S*::
+ Set 'sip' based on sname field/option 66 (by direct IP if a
+ period-delimited address or otherwise DNS).
*-t* 'SECONDS'::
- PXELINUX timeout (DHCP Option 211).
+ 'timeout' option for PXELINUX (DHCP Option 211).
// *-u*::
-// Copy UUID (Option 97) if found in packet #1
+// Copy 'UUID' (Option 97) if found in packet #1
*-w*::
- wait after loading before booting for user input.
+ 'wait'. After loading, wait for user input before booting.
*-W*::
- Enable WDS (Windows Deployment Services) - specific options.
+ Enable 'WDS' (Windows Deployment Services) - specific options.
+ 'FILE' (or its overrides for DHCP fields siaddr and file) must point
+ at the WDS server.
+ *NOTE:* As of 2012-05-31, there is a known issue with gPXE/iPXE, at
+ least with undionly.kkpxe.
+// PXELINUX asks gPXE/iPXE to unload, reverting to an underlying stack
== DECIMAL INPUT ==
-All parameters that are defaulted to decimal format are processed by *strtoul*(3) with a base of 0 which allows alternate formats and finds a suitable non-space separating character.
+All parameters that are defaulted to decimal format are processed by
+*strtoul*(3) with a base of 0 which allows alternate formats and finds a
+suitable non-space separating character.
== EXAMPLES ==
-pxechn.c32 http://myhost.dom.loc/path/nbp.0 -c myconfig
- Load nbp.0 and set PXELINUX config (option 209).
-
-pxechn.c32 gpxelinux.0 -p http://172.16.23.1/tftp/ -w -c myconfig -o 15.s=domain.loc -o 6.x=0A:01:01:02:ac:17:4D:Ec -
- Load gpxelinux.0 from the current directory, set prefix, wait to execute, set first config, set the domain name and 2 domain name servers (case mixed to show insensitivity; 10.1.1.2 and 172.23.77.236).
-
-pxechn.c32 gpxelinux.0 -p http://172.16.23.1/tftp/ -w -X A012345678 -x 197:00d0de00
-pxechn.c32 gpxelinux.0 -p http://172.16.23.1/tftp/ -w -X A012:3456:78 -x 197:00-d0-de-00
- Both of these are equivalent. Load gpxelinux.0 (relative to the current directory and not altering sname/option 66), set the PXELINUX path prefix, wait after loading, set option 160 to 0x12 0x34 0x56 0x78, and option 197 to 0x00 0xD0 0xDE 0x00.
+`pxechn.c32 http://myhost.dom.loc/path/nbp.0 -c myconfig`::
+ Load nbp.0 and set PXELINUX config (option 209).
+
+`pxechn.c32 gpxelinux.0 -p http://10.1.1.4/tftp/ -w -c myconfig -o 15.s=domain.loc -o 6.x=0A:01:01:02:ac:17:4D:Ec -`::
+ Load gpxelinux.0 from the current directory, set prefix, wait to
+ execute, set first config, set the domain name and 2 domain name
+ servers (case mixed to show insensitivity; 10.1.1.2 and
+ 172.23.77.236).
+
+`pxechn.c32 gpxelinux.0 -p http://10.1.1.4/tftp/ -w -o 0xA0.x=12:34:56:78 -x 197.x=00:d0:de:00`::
+ Load gpxelinux.0 (relative to the current directory and not
+ altering sname/option 66), set the PXELINUX path prefix, wait after
+ loading, set option 160 to 0x12 0x34 0x56 0x78, and option 197 to
+ 0x00 0xD0 0xDE 0x00.
+
+`pxechn.c32 10.1.1.8:boot\x86\wdsnbp.com -W`::
+ Load wdsnbp.com from 10.1.1.8 and copy DHCP Option 66 to DHCP
+ field sname if there's room.
+
+`pxechn.c32 10.1.1.4:boot\x86\wdsnbp.com -W -o 66.x=0a:01:01:08 -S`::
+ Load wdsnbp.com from 10.1.1.4, point packets to 10.1.1.8 for use
+ with WDS, copy DHCP Option 66 to DHCP field sname if there's room
+ and decode this to an IPv4 address.
== NOTES ==
-Please note that some NBPs may ignore packet #3 by either not examining it at all or by issuing its own DHCP DISCOVER/REQUEST, negating all DHCP field/option modifications by pxechn.c32.
+Please note that some NBPs may ignore packet #3 by either not examining
+it at all or by issuing its own DHCP DISCOVER/REQUEST, negating all DHCP
+field/option modifications by pxechn.c32, including Microsoft Windows
+Server 2008R2 WDS's wdsnbp.com. See also option '-W'.
-URL specifications in 'FILE' that include user/password before the host will currently cause the siaddr field to not be set properly.
+URL specifications in 'FILE' that include user/password before the host
+will currently cause the siaddr field to not be set properly.
-The non-space constraint is due to how Syslinux variants parse the command line as of 2012-01-12.
+The non-space constraint is due to how Syslinux variants parse the
+command line as of 2012-09-16.
== AUTHOR ==
@@ -91,4 +134,5 @@ The non-space constraint is due to how Syslinux variants parse the command line
== COPYRIGHT ==
Copyright \(C) 2012 {author}. Free use of this software is granted under
-the terms of the GNU General Public License (GPL).
+the terms of the GNU General Public License (GPL), version 2 (GPLv2)
+(or, at your option, any later version).