summaryrefslogtreecommitdiff
path: root/sys/arch/amd64
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2019-05-15 06:52:34 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2019-05-15 06:52:34 +0000
commitbf5ab008b624e055d4f345e1fc499cd78cce8eb6 (patch)
treea7430d172da7865ad13f46662905b673a0fa8dd8 /sys/arch/amd64
parent2a6f03d90f6061ad7ffefc8e5be51a91a384b83c (diff)
Add support to the BIOS bootloader for random kernel base VA
This diff adds support to be able to load a randomly linked kernel VA (subject to some range restrictions). This change has been in snaps for a few days without any fallout. ok deraadt@
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r--sys/arch/amd64/include/loadfile_machdep.h4
-rw-r--r--sys/arch/amd64/stand/boot/Makefile4
-rw-r--r--sys/arch/amd64/stand/boot/conf.c4
-rw-r--r--sys/arch/amd64/stand/cdboot/Makefile4
-rw-r--r--sys/arch/amd64/stand/cdboot/conf.c4
-rw-r--r--sys/arch/amd64/stand/libsa/exec_i386.c204
-rw-r--r--sys/arch/amd64/stand/libsa/run_amd64.S175
-rw-r--r--sys/arch/amd64/stand/pxeboot/Makefile4
-rw-r--r--sys/arch/amd64/stand/pxeboot/conf.c4
9 files changed, 380 insertions, 27 deletions
diff --git a/sys/arch/amd64/include/loadfile_machdep.h b/sys/arch/amd64/include/loadfile_machdep.h
index 5ee23dc8661..109ad40d990 100644
--- a/sys/arch/amd64/include/loadfile_machdep.h
+++ b/sys/arch/amd64/include/loadfile_machdep.h
@@ -1,5 +1,5 @@
/* XXX - DSR */
-/* $OpenBSD: loadfile_machdep.h,v 1.7 2019/04/10 04:17:33 deraadt Exp $ */
+/* $OpenBSD: loadfile_machdep.h,v 1.8 2019/05/15 06:52:33 mlarkin Exp $ */
/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */
/*-
@@ -46,7 +46,7 @@ extern u_long efi_loadaddr;
#define LOADADDR(a) (((((u_long)(a)) + offset)&0xfffffff) + \
efi_loadaddr)
#else
-#define LOADADDR(a) ((((u_long)(a)) + offset)&0xfffffff)
+#define LOADADDR(a) ((a) + offset)
#endif
#define ALIGNENTRY(a) ((u_long)(a))
#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c))
diff --git a/sys/arch/amd64/stand/boot/Makefile b/sys/arch/amd64/stand/boot/Makefile
index c75a1956efe..a96ae53fb18 100644
--- a/sys/arch/amd64/stand/boot/Makefile
+++ b/sys/arch/amd64/stand/boot/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.40 2019/04/20 22:59:03 deraadt Exp $
+# $OpenBSD: Makefile,v 1.41 2019/05/15 06:52:33 mlarkin Exp $
COPTS?=
MAN?= boot.8
@@ -24,7 +24,7 @@ LDFLAGS+=-melf_i386 -L/usr/libdata
SRCS+= boot.c bootarg.c cmd.c vars.c
.PATH: ${SADIR}/libsa
-SRCS+= gidt.S random_i386.S
+SRCS+= gidt.S random_i386.S run_amd64.S
SRCS+= cmd_i386.c dev_i386.c exec_i386.c gateA20.c machdep.c
SRCS+= bioscons.c biosdev.c diskprobe.c memprobe.c time.c
.if ${SOFTRAID:L} == "yes"
diff --git a/sys/arch/amd64/stand/boot/conf.c b/sys/arch/amd64/stand/boot/conf.c
index d784a7eacac..7709bfeb608 100644
--- a/sys/arch/amd64/stand/boot/conf.c
+++ b/sys/arch/amd64/stand/boot/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.45 2019/05/11 22:09:48 mlarkin Exp $ */
+/* $OpenBSD: conf.c,v 1.46 2019/05/15 06:52:33 mlarkin Exp $ */
/*
* Copyright (c) 1996 Michael Shalayeff
@@ -40,7 +40,7 @@
#include <biosdev.h>
#include <dev/cons.h>
-const char version[] = "3.43";
+const char version[] = "3.44";
int debug = 1;
diff --git a/sys/arch/amd64/stand/cdboot/Makefile b/sys/arch/amd64/stand/cdboot/Makefile
index ff43909149e..fd09735657e 100644
--- a/sys/arch/amd64/stand/cdboot/Makefile
+++ b/sys/arch/amd64/stand/cdboot/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.35 2019/04/20 22:59:03 deraadt Exp $
+# $OpenBSD: Makefile,v 1.36 2019/05/15 06:52:33 mlarkin Exp $
MAN= cdboot.8
@@ -18,7 +18,7 @@ BINMODE=644
.PATH: ${SADIR}/libsa
SRCS+= machdep.c dev_i386.c exec_i386.c cmd_i386.c
SRCS+= gidt.S random_i386.S biosdev.c bioscons.c gateA20.c \
- memprobe.c diskprobe.c time.c
+ memprobe.c diskprobe.c time.c run_amd64.S
SRCS+= softraid_amd64.c
.PATH: ${S}/stand/boot
diff --git a/sys/arch/amd64/stand/cdboot/conf.c b/sys/arch/amd64/stand/cdboot/conf.c
index 582ad251ff2..9731de7c436 100644
--- a/sys/arch/amd64/stand/cdboot/conf.c
+++ b/sys/arch/amd64/stand/cdboot/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.39 2019/05/11 22:12:18 mlarkin Exp $ */
+/* $OpenBSD: conf.c,v 1.40 2019/05/15 06:52:33 mlarkin Exp $ */
/*
* Copyright (c) 2004 Tom Cosgrove
@@ -41,7 +41,7 @@
#include <biosdev.h>
#include <dev/cons.h>
-const char version[] = "3.42";
+const char version[] = "3.43";
int debug = 1;
diff --git a/sys/arch/amd64/stand/libsa/exec_i386.c b/sys/arch/amd64/stand/libsa/exec_i386.c
index 4b6aed12123..e7b7fc24826 100644
--- a/sys/arch/amd64/stand/libsa/exec_i386.c
+++ b/sys/arch/amd64/stand/libsa/exec_i386.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec_i386.c,v 1.29 2019/05/10 21:20:43 mlarkin Exp $ */
+/* $OpenBSD: exec_i386.c,v 1.30 2019/05/15 06:52:33 mlarkin Exp $ */
/*
* Copyright (c) 1997-1998 Michael Shalayeff
@@ -33,6 +33,7 @@
#include <dev/cons.h>
#include <lib/libsa/loadfile.h>
#include <machine/biosvar.h>
+#include <machine/pte.h>
#include <machine/specialreg.h>
#include <stand/boot/bootarg.h>
@@ -46,21 +47,48 @@
#include "softraid_amd64.h"
#endif
+#define BOOT_DEBUG
+
+#ifdef BOOT_DEBUG
+#define DPRINTF(x...) do { printf(x); } while(0)
+#else
+#define DPRINTF(x...)
+#endif /* BOOT_DEBUG */
+
+#define LEGACY_KERNEL_ENTRY_POINT 0xffffffff81001000ULL
+
typedef void (*startfuncp)(int, int, int, int, int, int, int, int)
__attribute__ ((noreturn));
+extern void launch_amd64_kernel_long(caddr_t, caddr_t, caddr_t, uint64_t, int,
+ int, int, uint64_t, int, int, int, uint64_t);
+
+caddr_t boot_alloc(void);
+caddr_t make_kernel_page_tables(uint64_t);
+
void ucode_load(void);
extern struct cmd_state cmd;
char *bootmac = NULL;
+extern char end[], _start[];
+
+caddr_t pt_base_addr;
+
+#define PAGE_MASK (PAGE_SIZE - 1)
+#define LONG_KERN_PML4_ADDR1 0x1000
+#define LONG_KERN_PML4_ADDR2 (((uint64_t)(end) + PAGE_MASK) & ~PAGE_MASK)
+
+/*
+ * N.B. - The following must stay in sync with pmap.h (including that here
+ * causes compile errors related to RBT_HEAD.
+ */
+#define NKL2_KIMG_ENTRIES 64
void
run_loadfile(uint64_t *marks, int howto)
{
- u_long entry;
-#ifdef EXEC_DEBUG
- extern int debug;
-#endif
+ uint64_t entry;
+ int long_kernel;
dev_t bootdev = bootdev_dip->bootdev;
size_t ac = BOOTARG_LEN;
caddr_t av = (caddr_t)BOOTARG_OFF;
@@ -70,10 +98,11 @@ run_loadfile(uint64_t *marks, int howto)
bios_ddb_t ddb;
extern int db_console;
bios_bootduid_t bootduid;
+ caddr_t pml4, stack, new_av;
#ifdef SOFTRAID
bios_bootsr_t bootsr;
struct sr_boot_volume *bv;
-#endif
+#endif /* SOFTRAID */
if (sa_cleanup != NULL)
(*sa_cleanup)();
@@ -109,21 +138,58 @@ run_loadfile(uint64_t *marks, int howto)
}
sr_clear_keys();
-#endif
+#endif /* SOFTRAID */
+
+ entry = marks[MARK_ENTRY];
- entry = marks[MARK_ENTRY] & 0x0fffffff;
+ printf("entry point at 0x%llx\n", entry);
- printf("entry point at 0x%lx\n", entry);
+ pt_base_addr = (caddr_t)LONG_KERN_PML4_ADDR1;
/* Pass memory map to the kernel */
mem_pass();
makebootargs(av, &ac);
- /* stack and the gung is ok at this point, so, no need for asm setup */
- (*(startfuncp)entry)(howto, bootdev, BOOTARG_APIVER, marks[MARK_END],
- extmem, cnvmem, ac, (int)av);
-
+ /*
+ * Legacy kernels have entry set to 0xffffffff81001000.
+ * Other entry values indicate kernels that have random
+ * base VA and launch in 64 bit (long) mode.
+ */
+ if (marks[MARK_ENTRY] == LEGACY_KERNEL_ENTRY_POINT) {
+ /*
+ * Legacy boot code expects entry 0x1001000, so mask
+ * off the high bits.
+ */
+ entry &= 0xFFFFFFF;
+ long_kernel = 0;
+ } else
+ long_kernel = 1;
+
+ /*
+ * Launch a long mode/randomly linked (post-6.5) kernel?
+ */
+ if (long_kernel) {
+ new_av = boot_alloc(); /* Replaces old heap */
+ memcpy((void *)new_av, av, ac);
+
+ /* Stack grows down, so grab two pages. We'll waste the 2nd */
+ stack = boot_alloc();
+ stack = boot_alloc();
+
+ pml4 = make_kernel_page_tables(marks[MARK_ENTRY]);
+ launch_amd64_kernel_long((void *)launch_amd64_kernel_long,
+ pml4, stack, marks[MARK_ENTRY], howto,
+ bootdev, BOOTARG_APIVER, marks[MARK_END],
+ extmem, cnvmem, ac, (uint64_t)new_av);
+ } else {
+ /*
+ * Launch a legacy kernel
+ */
+
+ (*(startfuncp)entry)(howto, bootdev, BOOTARG_APIVER,
+ marks[MARK_END] & 0xfffffff, extmem, cnvmem, ac, (int)av);
+ }
/* not reached */
}
@@ -183,3 +249,115 @@ ucode_load(void)
close(fd);
}
+
+/*
+ * boot_alloc
+ *
+ * Special allocator for page table pages and kernel stack
+ *
+ * Allocates 1 page (PAGE_SIZE) of data.
+ *
+ * We have 2 regions available to us:
+ * 0x1000 ... 0xF000 : range 1 (stack is at 0xF000)
+ * end ... 0xA0000 (640KB) : range 2
+ *
+ * We allocate from range 1 until it is complete, then skip to range 2. If
+ * range 2 is exhausted, we panic.
+ *
+ * Return value:
+ * VA of requested allocation
+ */
+caddr_t
+boot_alloc(void)
+{
+ caddr_t ret;
+ static caddr_t cur = 0;
+ static int skipped = 0;
+
+ /* First time? */
+ if (cur == 0)
+ cur = (caddr_t)pt_base_addr;
+
+ ret = cur;
+
+ if (((uint64_t)cur + PAGE_SIZE >= 0xF000) && !skipped) {
+ cur = (caddr_t)LONG_KERN_PML4_ADDR2;
+ skipped = 1;
+ } else
+ cur += PAGE_SIZE;
+
+ if ((uint64_t)cur >= 640 * 1024)
+ panic("out of memory");
+
+ return ret;
+}
+
+/*
+ * make_kernel_page_tables
+ *
+ * Sets up a minimal set of page tables for early use in the kernel. In
+ * pre_init_x86_64, the kernel will rebuild its page tables, so the
+ * table constructed here only needs the minimal mapping.
+ *
+ * [entry ... end] => PA 0x1000000 (16MB, the current phys loadaddr)
+ *
+ * In BIOS boot mode, this function overwrites the heap with the long
+ * mode kernel boostrap page tables and thus must be called immediately
+ * before switching to long mode and starting the kernel.
+ *
+ * Parameters:
+ * entry_lo: the low byte (masked) of the kernel entry point
+ *
+ * Return value:
+ * PML4 PA of the new table
+ */
+caddr_t
+make_kernel_page_tables(uint64_t entry)
+{
+ uint64_t *pml4, *pml3, *pml2, *pml1;
+ int i, j, k, kern_pml4, kern_pml3, kern_pml2, kern_pml1;
+
+ kern_pml4 = (entry & L4_MASK) >> L4_SHIFT;
+ kern_pml3 = (entry & L3_MASK) >> L3_SHIFT;
+ kern_pml2 = (entry & L2_MASK) >> L2_SHIFT;
+ kern_pml1 = (entry & L1_MASK) >> L1_SHIFT;
+
+ pml4 = (uint64_t *)boot_alloc();
+
+ /* Map kernel */
+ pml3 = (uint64_t *)boot_alloc();
+ pml4[kern_pml4] = (uint64_t)pml3 | PG_V | PG_RW;
+
+ pml2 = (uint64_t *)boot_alloc();
+ pml3[kern_pml3] = (uint64_t)pml2 | PG_V | PG_RW;
+
+ for (i = 0; i < NKL2_KIMG_ENTRIES; i++) {
+ pml1 = (uint64_t *)boot_alloc();
+ pml2[i + kern_pml2] = (uint64_t)pml1 | PG_V | PG_RW;
+
+ /* The first page of PTEs may start at a different offset */
+ if (i == kern_pml2)
+ k = kern_pml1;
+ else
+ k = 0;
+
+ /*
+ * Map [k...511] PTEs.
+ */
+ for (j = k; j < 512; j++)
+ pml1[j] = (uint64_t)(((8 + i) * NBPD_L2) +
+ (j - kern_pml1) * PAGE_SIZE) | PG_V | PG_RW;
+ }
+
+ /* Map first 4GB phys for kernel page table, stack, and bootstrap */
+ pml3 = (uint64_t *)boot_alloc();
+ pml4[0] = (uint64_t)pml3 | PG_V | PG_RW; /* Covers 0-512GB */
+
+ pml2 = (uint64_t *)boot_alloc();
+ pml3[0] = (uint64_t)pml2 | PG_V | PG_RW; /* Covers 0-1GB */
+
+ for (i = 0; i < 512; i++)
+ pml2[i] = (i << 21) | PG_V | PG_RW | PG_PS;
+
+ return (caddr_t)pml4;
+}
diff --git a/sys/arch/amd64/stand/libsa/run_amd64.S b/sys/arch/amd64/stand/libsa/run_amd64.S
new file mode 100644
index 00000000000..d6640cdc585
--- /dev/null
+++ b/sys/arch/amd64/stand/libsa/run_amd64.S
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2019 Mike Larkin <mlarkin@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <machine/asm.h>
+#include <machine/specialreg.h>
+
+#define CODE_SEGMENT 0x8
+#define DATA_SEGMENT 0x10
+
+ .text
+ .code32
+ .global _C_LABEL(launch_amd64_kernel_long)
+ /*
+ * void launch_amd64_kernel_long(caddr_t base, caddr_t pml4,
+ * caddr_t rsp, uint64_t entry, int boothowto, int bootdev,
+ * int bootapiver, uint64_t end, int extmem, int cnvmem,
+ * int ac, uint64_t av);
+ */
+_C_LABEL(launch_amd64_kernel_long):
+asm_start:
+ xchg %bx, %bx
+
+ /*
+ * We are in 32 bit mode
+ * - compute indirect jump targets
+ * - compute GDT locations
+ */
+ popl %edi /* Discard return address */
+ popl %edi /* %edi = bootloader base address */
+
+ /* Current mode -> 32 bit jump target */
+ leal (prot_mode - asm_start)(%edi), %eax
+ movl %eax, (start32r - asm_start)(%edi)
+
+ /* 32 bit -> 64 bit jump target */
+ leal (long_mode - asm_start)(%edi), %eax
+ movl %eax, (start64r - asm_start)(%edi)
+
+ /* Current mode -> 32 bit GDT */
+ leal (gdt32 - asm_start)(%edi), %eax
+ movl %eax, (gdtrr32 - asm_start)(%edi)
+
+ /* 32 bit -> 64 bit GDT */
+ leal (gdt64 - asm_start)(%edi), %eax
+ movl %eax, (gdtrr64 - asm_start)(%edi)
+
+ cli
+
+ lgdtl (gdtr32 - asm_start)(%edi)
+
+ mov %cr0, %eax
+ orl $(CR0_PE), %eax
+ mov %eax, %cr0
+
+ ljmpl *(start32r - asm_start)(%edi)
+
+ .align 4
+prot_mode:
+ movw $DATA_SEGMENT, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %gs
+ movw %ax, %ss
+ movw %ax, %fs
+
+ mov $(CR4_PAE | CR4_PSE), %eax
+ mov %eax, %cr4
+
+ lgdtl (gdtr64 - asm_start)(%edi)
+ movl $MSR_EFER, %ecx
+ xorl %edx, %edx
+ movl $(EFER_LME | EFER_NXE | EFER_SCE), %eax
+ wrmsr
+
+ movl (%esp), %eax /* first arg - PML4 */
+ movl 4(%esp), %ebx /* second arg - kernel stack */
+ movl %eax, %cr3
+
+ jmp 1f
+1: jmp 1f
+1: movl %cr0, %eax
+ orl $CR0_DEFAULT, %eax
+ movl %eax, %cr0
+
+ jmp 1f
+1: jmp 1f
+1: ljmpl *(start64r - asm_start)(%edi)
+
+long_mode:
+ .code64
+ movq %rsp, %rax
+ movq %rbx, %rsp
+
+ /*
+ * params stack at %rax right now:
+ *
+ * +0 32 bit PML4 ptr
+ * +4 32 bit kernel stack
+ * +8 start va low bytes
+ + +12 start va high bytes
+ * +16 boothowto (%rdi)
+ * +20 bootdev (%rsi)
+ * +24 BOOTARG_APIVER (%rdx)
+ * +28 marks[MARK_END] low bytes (%rcx)
+ * +32 marks[MARK_END] high bytes (%rcx)
+ * +36 extmem (%r8)
+ * +40 cnvmem (%r9)
+ * +44 ac (%rsp, will be %rsp + 8 after call below)
+ * +48 av low bytes (%rsp + 8, will be %rsp + 16 after call below)
+ * +52 av high bytes (%rsp + 16, will be %rsp + 24 after call below)
+ */
+
+ movl 16(%rax), %edi
+ movl 20(%rax), %esi
+ movl 24(%rax), %edx
+ movq 28(%rax), %rcx
+ movl 36(%rax), %r8d
+ movl 40(%rax), %r9d
+ movq 48(%rax), %rbx /* av */
+ pushq %rbx
+ movl 44(%rax), %ebx /* ac */
+ pushq %rbx
+ movq 8(%rax), %r11
+
+ /*
+ * start(howto, bootdev, BOOTARG_APIVER, marks[MARK_END],
+ * extmem, cnvmem, ac, av);
+ */
+ call *%r11
+
+ cli
+ hlt
+ /* NOTREACHED */
+
+ .align 4
+start32r:
+ .long 0
+ .long CODE_SEGMENT
+
+start64r:
+ .long 0
+ .long CODE_SEGMENT
+
+gdt32:
+ .long 0, 0
+ .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9f, 0xcf, 0x00
+ .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x93, 0xcf, 0x00
+gdtr32:
+ .word gdtr32 - gdt32
+gdtrr32:
+ .quad
+
+ .align 8
+gdt64:
+ .quad 0x0000000000000000
+ .quad 0x00af9a000000ffff
+ .quad 0x00cf92000000ffff
+
+gdtr64:
+ .word gdtr64 - gdt64
+gdtrr64:
+ .quad
diff --git a/sys/arch/amd64/stand/pxeboot/Makefile b/sys/arch/amd64/stand/pxeboot/Makefile
index 9b76c21d153..12948210cee 100644
--- a/sys/arch/amd64/stand/pxeboot/Makefile
+++ b/sys/arch/amd64/stand/pxeboot/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.33 2019/04/20 22:59:03 deraadt Exp $
+# $OpenBSD: Makefile,v 1.34 2019/05/15 06:52:33 mlarkin Exp $
MAN= pxeboot.8
@@ -17,7 +17,7 @@ BINMODE=644
.PATH: ${SADIR}/libsa
# i386 stuff (so, it will possibly load in the same 64k)
-SRCS+= machdep.c exec_i386.c cmd_i386.c
+SRCS+= machdep.c exec_i386.c cmd_i386.c run_amd64.S
SRCS+= gidt.S random_i386.S biosdev.c bioscons.c gateA20.c \
memprobe.c diskprobe.c time.c ## biosprobe.c
SRCS+= pxe.c pxe_call.S pxe_net.c pxe_udp.c
diff --git a/sys/arch/amd64/stand/pxeboot/conf.c b/sys/arch/amd64/stand/pxeboot/conf.c
index 00ec2c2a40e..bef9e5f520f 100644
--- a/sys/arch/amd64/stand/pxeboot/conf.c
+++ b/sys/arch/amd64/stand/pxeboot/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.43 2019/05/11 22:13:26 mlarkin Exp $ */
+/* $OpenBSD: conf.c,v 1.44 2019/05/15 06:52:33 mlarkin Exp $ */
/*
* Copyright (c) 2004 Tom Cosgrove
@@ -43,7 +43,7 @@
#include "pxeboot.h"
#include "pxe_net.h"
-const char version[] = "3.42";
+const char version[] = "3.43";
int debug = 0;
void (*sa_cleanup)(void) = pxe_shutdown;