From 89bb0903fe73caa9c3cebf20c2262fa70b8aa53a Mon Sep 17 00:00:00 2001 From: Thomas Oltmann Date: Sat, 28 Feb 2026 15:57:51 +0100 Subject: [PATCH] Finding both the PXENV+ and !PXE structs --- Makefile | 1 + src/main.c | 46 +++++++++++++++++++++++++++++++++++++++++----- src/nbp.S | 31 +++++++++++++++++++++++++++---- src/pxe.S | 24 ++++++++++++++++++++++++ src/std.c | 13 ++++++++++++- 5 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 src/pxe.S diff --git a/Makefile b/Makefile index f723508..2ee26e6 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ OBJS=\ src/nbp.o \ src/bios.o \ + src/pxe.o \ src/std.o \ src/main.o \ # end of object list diff --git a/src/main.c b/src/main.c index 391506b..5663678 100644 --- a/src/main.c +++ b/src/main.c @@ -115,22 +115,58 @@ pg_setup() return cr3; } +struct PXENV { + uint8_t signature[6]; + uint16_t version; + uint8_t length; + uint8_t checksum; + uint32_t rmentry; + uint32_t pmoffset; +}; + +struct exPXE { + uint8_t signature[4]; + uint8_t length; + uint8_t checksum; + uint8_t revision; + uint8_t reserved; + uint32_t undiromid; + uint32_t bcromid; + uint32_t rmentry; + uint32_t pmentry; +}; + +//extern uint32_t pxe_call(uint16_t func, offset, segment); + +extern struct PXENV *PXENV; +extern struct exPXE *exPXE; + void main() { - //blank_screen(0x10); - //move_cursor(0, 0); - display_string(0x14, "Netboot via fernlader v2 ...\r\n"); + blank_screen(0x10); + move_cursor(0, 0); + //display_string(0x14, "Netboot via fernlader v2 ...\r\n"); bios_write("Going well ...\r\n"); + if (memcmp(PXENV->signature, "PXENV+", 6) != 0) { + bios_write("missing PXENV+ signature\r\n"); + } + if (PXENV->version >= 0x0201) { + bios_write("!PXE version\r\n"); + if (memcmp(exPXE->signature, "!PXE", 4) != 0) { + bios_write("missing !PXE signature\r\n"); + } + } + memcpy(bootboot.magic, BOOTBOOT_MAGIC, sizeof bootboot.magic); bootboot.size = 128; bootboot.protocol = PROTOCOL_MINIMAL | LOADER_BIOS; bootboot.numcores = 1; - display_string(0x0E, "init\r\n"); + //display_string(0x0E, "init\r\n"); struct e820_entry *end = bios_getmap(memmap); - display_string(0x0E, "karlos\r\n"); + //display_string(0x0E, "karlos\r\n"); for (int i = 0; ; i++) { if (&memmap[i] >= end) break; char buf[2]; diff --git a/src/nbp.S b/src/nbp.S index fc81945..4e9ed61 100644 --- a/src/nbp.S +++ b/src/nbp.S @@ -9,20 +9,37 @@ // _start: entry point _start: cli cld + + mov %ss, %ax + mov %ax, %cs:real_ss + + xor %eax, %eax + mov %es, %ax + shl $4, %eax + movzwl %bx, %ebx + add %eax, %ebx + mov %ebx, %cs:PXENV + + xor %eax, %eax + xor %ebx, %ebx + mov %sp, %bx + mov %ss:6(%bx), %ax + mov %ss:4(%bx), %bx + shl $4, %eax + add %eax, %ebx + mov %ebx, %cs:exPXE + mov %sp, %bp xor %ax, %ax mov %ax, %ds mov %ax, %es - mov %ss, %ax - mov %ax, real_ss - // initialize our own BSS section mov $_bss_start, %di mov $_bss_end, %cx sub %di, %cx xor %al, %al - rep stosb + rep stosb // a20_enable: Allow use of 'high' (>1Mb) memory a20_enable: // Of all the ways to toggle A20, we only try the Fast A20 Gate. @@ -45,6 +62,12 @@ prot_enter: lgdt GDT_PTR .data + .global PXENV +PXENV: .long 0 + + .global exPXE +exPXE: .long 0 + .global real_ss real_ss: .word 0 diff --git a/src/pxe.S b/src/pxe.S new file mode 100644 index 0000000..99b53db --- /dev/null +++ b/src/pxe.S @@ -0,0 +1,24 @@ + // vim: ft=gas:et:sw=12:ts=12:sts=12 + + .include "src/mode.S" + + .data + +pxe_entry: .word 0 + + .text + .global pxe_call + .code32 +pxe_call: push %ebp + mov %esp, %ebp + + PROT16 + + call (pxe_entry) + push %eax + + PROT32 + + pop %eax + leave + ret diff --git a/src/std.c b/src/std.c index e2057c2..07b73d9 100644 --- a/src/std.c +++ b/src/std.c @@ -7,10 +7,21 @@ memcpy(void *dst, const void *src, size_t n) __asm__ ("rep movsb" : "+D"(di), "+S"(src), "+c"(n) : - : "memory"); + : "cc", "memory"); return dst; } +int +memcmp(const void *src1, const void *src2, size_t n) +{ + __asm__ ("repe cmpsb" + : "+D"(src2), "+S"(src1), "+c"(n) + : + : "cc", "memory"); + if (n == 0) return 0; + return src1 < src2 ? -1 : 1; +} + size_t strlen(const char *s) {