Current-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: PXE entry invalid, so PXE boot hangs
On Fri, Mar 27, 2015 at 09:46:54AM +0000, Stephen Borrill wrote:
> I'm trying to PXE boot an x86 box. The setup works fine on all my other kit,
> but on the problem one I see:
>
> booting netbsd - starting in 0 seconds.
> pxe_init: bad cksum (0xbc) for PXENV+ at 0x900d8
> PXE BIOS Version 2.1
> *hang*
>
> I'm prepared for a flaky BIOS, but it does boot pxelinux and Citrix
> Provisioning Services OK.
>
> Adding a few printfs, I see it found PXENV+ at two locations: 0x900d8
> (rejected as bad checksum) and 0x8bb52. PXE+ was found at 0x8baf2. As it's
> PXE BIOS 2.1, it ignores the PXENV+ info. The hang is because it never
> returns from this call:
>
> pxe_call(PXENV_GET_CACHED_INFO);
>
> http://nxr.netbsd.org/xref/src/sys/arch/i386/stand/pxeboot/pxe.c#380
>
> pxelinux uses 5 methods in priority order to find the pxe structure. NetBSD
> only uses a memory scan which is combination of its final 2 (it calls these
> plans D and E).
>
> pxelinux prints:
> !PXE entry point found (we hope) at 8A44:0100 via plan A
>
> http://git.kernel.org/cgit/boot/syslinux/syslinux.git/tree/core/fs/pxe/bios.c?id=a7f5892c4d85f3685708b8efb237c9c73a8b1ddf#n240
>
> These addresses correspond to bangpxe_seg and bangpxe_off:
> http://nxr.netbsd.org/xref/src/sys/arch/i386/stand/pxeboot/pxe.c#360
>
> Printing these shows that bangpxe_reg is 0, not 0x8a44. Hardwiring
> bangpxe_reg to 0x8a44 gets the machine booting (well, the kernel panics
> later on, but that's a different story).
>
> Therefore, it looks like the structure found by memory scanning is incorrect
> and perhaps we should implement Linux's plans A and B (C being the int 0x1a
> function 0x5650 that we explicitly choose not to support). These involve
> reading points from offsets relative to InitStack. Where does this
> correspond to in NetBSD?
Is InitStack = 0xfffc ?
Untested patch attached...
Cheers,
Patrick
diff --git a/pxe.c b/pxe.c
index 3a094bf..650d74c 100644
--- a/pxe.c
+++ b/pxe.c
@@ -276,6 +276,21 @@ extern uint16_t pxenv_off, pxenv_seg;
static struct btinfo_netif bi_netif;
+static int
+check_pxe(const uint8_t *pxe, const uint8_t pxelen, const char *msg)
+{
+ uint8_t i, cksum;
+
+ for (i = 0, cksum = 0; i < pxelen; i++)
+ cksum += pxe[i];
+ if (cksum != 0) {
+ printf("pxe_init: bad cksum (0x%x) for %s at 0x%lx\n",
+ cksum, msg, (u_long) pxe);
+ }
+
+ return (cksum == 0);
+}
+
int
pxe_init(void)
{
@@ -284,8 +299,7 @@ pxe_init(void)
pxenv_t *pxenv;
pxe_t *pxe;
char *cp;
- int i;
- uint8_t cksum, *ucp;
+ SEGOFF16_t *bangpxe_addr;
/*
* Checking for the presence of PXE is a machine-dependent
@@ -299,46 +313,51 @@ pxe_init(void)
* to a deprecated structure (PXENV+).
*/
+ /*
+ * The above comment is presumably taken from 3.1 p40 of spec v2.1.
+ * As we are a "Network Bootstrap Program" (NBP), we don't need
+ * the above installation check procedures as according to 4.4.5 p88,
+ * we can use:
+ *
+ * !PXE structure at SS:[SP+4]
+ *
+ * PXENV+ structure at ES:BX (obsolete)
+ *
+ * and from pxe_start.S, SS:SP=0xfffc
+ */
+
pxenv = NULL;
pxe = NULL;
- for (cp = (char *)0xa0000; cp > (char *)0x10000; cp -= 2) {
- if (pxenv == NULL) {
- pxenv = (pxenv_t *)cp;
- if (MEMSTRCMP(pxenv->Signature, "PXENV+"))
- pxenv = NULL;
- else {
- for (i = 0, ucp = (uint8_t *)cp, cksum = 0;
- i < pxenv->Length; i++)
- cksum += ucp[i];
- if (cksum != 0) {
- printf("pxe_init: bad cksum (0x%x) "
- "for PXENV+ at 0x%lx\n", cksum,
- (u_long) cp);
+ bangpxe_addr = (SEGOFF16_t *)(0xfffc + 4);
+ pxe = (pxe_t *)(bangpxe_addr->segment * 0x10 + bangpxe_addr->offset);
+ if (!check_pxe((uint8_t *)pxe, pxe->StructLength, "NBP !PXE")) {
+ pxe = NULL;
+ for (cp = (char *)0xa0000; cp > (char *)0x10000; cp -= 2) {
+ if (pxenv == NULL) {
+ pxenv = (pxenv_t *)cp;
+ if (MEMSTRCMP(pxenv->Signature, "PXENV+"))
pxenv = NULL;
+ else {
+ if (!check_pxe((uint8_t *)pxenv,
+ pxenv->Length, "PXENV+"))
+ pxenv = NULL;
}
}
- }
- if (pxe == NULL) {
- pxe = (pxe_t *)cp;
- if (MEMSTRCMP(pxe->Signature, "!PXE"))
- pxe = NULL;
- else {
- for (i = 0, ucp = (uint8_t *)cp, cksum = 0;
- i < pxe->StructLength; i++)
- cksum += ucp[i];
- if (cksum != 0) {
- printf("pxe_init: bad cksum (0x%x) "
- "for !PXE at 0x%lx\n", cksum,
- (u_long) cp);
+ if (pxe == NULL) {
+ pxe = (pxe_t *)cp;
+ if (MEMSTRCMP(pxe->Signature, "!PXE"))
pxe = NULL;
- }
+ else
+ if (!check_pxe((uint8_t *)pxe,
+ pxe->StructLength, "!PXE"))
+ pxe = NULL;
}
- }
- if (pxe != NULL && pxenv != NULL)
- break;
+ if (pxe != NULL && pxenv != NULL)
+ break;
+ }
}
if (pxe == NULL && pxenv == NULL) {
Home |
Main Index |
Thread Index |
Old Index