:: commit 5f1c34a58755d1d3c9ccf8a61d24dfd06d3fa407

mintsuki <mintsuki@protonmail.com> — 2021-08-12 05:40

parents: 294382e3bf

tftp: Overhaul and bug fixes

diff --git a/stage23/fs/file.s2.c b/stage23/fs/file.s2.c
index 2f42ab5b..74994402 100644
--- a/stage23/fs/file.s2.c
+++ b/stage23/fs/file.s2.c
@@ -28,16 +28,10 @@ int fopen(struct file_handle *ret, struct volume *part, const char *filename) {
 
 #if bios == 1
     if (part->pxe) {
-        struct tftp_file_handle *fd = ext_mem_alloc(sizeof(struct tftp_file_handle));
-
-        int r = tftp_open(fd, 0, 69, filename);
+        int r = tftp_open(ret, 0, 69, filename);
         if (r)
             return r;
 
-        ret->fd = (void *)fd;
-        ret->read = (void *)tftp_read;
-        ret->size = fd->file_size;
-
         return 0;
     }
 #endif
diff --git a/stage23/lib/config.c b/stage23/lib/config.c
index 640741fb..dc549373 100644
--- a/stage23/lib/config.c
+++ b/stage23/lib/config.c
@@ -35,14 +35,17 @@ int init_config_disk(struct volume *part) {
 
 #if bios == 1
 int init_config_pxe(void) {
-    struct tftp_file_handle cfg;
-    if (tftp_open(&cfg, 0, 69, "limine.cfg")) {
+    struct file_handle f;
+    if (tftp_open(&f, 0, 69, "limine.cfg")) {
         return -1;
     }
-    config_addr = ext_mem_alloc(cfg.file_size);
-    tftp_read(&cfg, config_addr, 0, cfg.file_size);
 
-    return init_config(cfg.file_size);
+    size_t config_size = f.size + 1;
+    config_addr = ext_mem_alloc(config_size);
+
+    fread(&f, config_addr, 0, f.size);
+
+    return init_config(config_size);
 }
 #endif
 
diff --git a/stage23/lib/pxe.asm b/stage23/lib/pxe.asm
index 70b4545b..af47b141 100644
--- a/stage23/lib/pxe.asm
+++ b/stage23/lib/pxe.asm
@@ -9,17 +9,23 @@ set_pxe_fp:
     ret
 
 pxe_call:
-   ; Save GDT in case BIOS overwrites it
+    ; Save GDT in case BIOS overwrites it
     sgdt [.gdt]
 
+    ; Save IDT
+    sidt [.idt]
+
+    ; Load BIOS IVT
+    lidt [.rm_idt]
+
     ; Save non-scratch GPRs
     push ebx
     push esi
     push edi
     push ebp
 
-    mov ebx, eax
-    
+    lea ebp, [esp + 20]
+
     ; Jump to real mode
     jmp 0x08:.bits16
   .bits16:
@@ -44,32 +50,36 @@ pxe_call:
 
     sti
 
-    push dx
-    push cx
-    push bx
+    push word [bp + 4]
+    push word [bp + 8]
+    push word [bp + 0]
     call far [.pxe_fp]
     add sp, 6
-    mov bx, ax
 
     cli
-   ; Restore GDT
-    lgdt [ss:.gdt]
+
+    ; Restore GDT
+    o32 lgdt [cs:.gdt]
+
+    ; Restore IDT
+    o32 lidt [cs:.idt]
 
     ; Jump back to pmode
-    mov eax, cr0
-    or al, 1
-    mov cr0, eax
+    mov ebx, cr0
+    or bl, 1
+    mov cr0, ebx
     jmp 0x18:.bits32
   .bits32:
     bits 32
-    mov ax, 0x20
-    mov ds, ax
-    mov es, ax
-    mov fs, ax
-    mov gs, ax
-    mov ss, ax
+    mov bx, 0x20
+    mov ds, bx
+    mov es, bx
+    mov fs, bx
+    mov gs, bx
+    mov ss, bx
+
+    and eax, 0xffff
 
-    mov eax, ebx
     ; Restore non-scratch GPRs
     pop ebp
     pop edi
@@ -81,5 +91,7 @@ pxe_call:
 
 align 16
   .pxe_fp:   dd 0
-  .esp:      dd 0
   .gdt:      dq 0
+  .idt:      dq 0
+  .rm_idt:   dw 0x3ff
+             dd 0
diff --git a/stage23/lib/uri.c b/stage23/lib/uri.c
index 4c6d0f53..c7eb1519 100644
--- a/stage23/lib/uri.c
+++ b/stage23/lib/uri.c
@@ -148,19 +148,14 @@ static bool uri_tftp_dispatch(struct file_handle *fd, char *root, char *path) {
         ip = 0;
     } else {
         if (inet_pton(root, &ip)) {
-            panic("invalid ipv4 address: %s", root);
+            panic("tftp: Invalid ipv4 address: %s", root);
         }
     }
 
-    struct tftp_file_handle *cfg = ext_mem_alloc(sizeof(struct tftp_file_handle));
-    if(tftp_open(cfg, ip, 69, path)) {
+    if (tftp_open(fd, ip, 69, path)) {
         return false;
     }
 
-    fd->is_memfile = false;
-    fd->fd = cfg;
-    fd->read = tftp_read;
-    fd->size = cfg->file_size;
     return true;
 }
 #endif
diff --git a/stage23/pxe/pxe.h b/stage23/pxe/pxe.h
index 84c86510..db148d2c 100644
--- a/stage23/pxe/pxe.h
+++ b/stage23/pxe/pxe.h
@@ -6,7 +6,7 @@
 
 struct volume *pxe_bind_volume(void);
 void pxe_init(void);
-int pxe_call(uint16_t opcode, uint16_t buf_seg, uint16_t buf_off) __attribute__((regparm(3)));
+int pxe_call(uint16_t opcode, uint16_t buf_seg, uint16_t buf_off);
 
 #define MAC_ADDR_LEN 16
 typedef uint8_t MAC_ADDR_t[MAC_ADDR_LEN];
diff --git a/stage23/pxe/tftp.h b/stage23/pxe/tftp.h
index 08d9cc26..60febf66 100644
--- a/stage23/pxe/tftp.h
+++ b/stage23/pxe/tftp.h
@@ -3,17 +3,10 @@
 
 #include <stdint.h>
 #include <stddef.h>
+#include <fs/file.h>
 
 #define UNDI_GET_INFORMATION 0xC
 
-struct tftp_file_handle {
-    uint32_t server_ip;
-    uint16_t server_port;
-    uint16_t packet_size;
-    size_t file_size;
-    void *data;
-};
-
 #define TFTP_OPEN 0x0020
 struct pxenv_open {
     uint16_t status;
@@ -45,8 +38,8 @@ struct pxenv_get_file_size {
 #define TFTP_CLOSE 0x21
 
 //server_ip and server_port can be 0 for default
-int tftp_open(struct tftp_file_handle* handle, uint32_t server_ip, uint16_t server_port, const char* name);
-int tftp_read(void *fd, void *buf, uint64_t loc, uint64_t count);
+int tftp_open(struct file_handle *handle, uint32_t server_ip, uint16_t server_port, const char *name);
+
 uint32_t get_boot_server_info(void);
 
 #endif
diff --git a/stage23/pxe/tftp.s2.c b/stage23/pxe/tftp.s2.c
index 6a2c705f..510b4e5a 100644
--- a/stage23/pxe/tftp.s2.c
+++ b/stage23/pxe/tftp.s2.c
@@ -16,14 +16,11 @@ uint32_t get_boot_server_info(void) {
     return ph->sip;
 }
 
-int tftp_open(struct tftp_file_handle *handle, uint32_t server_ip, uint16_t server_port, const char *name) {
+int tftp_open(struct file_handle *handle, uint32_t server_ip, uint16_t server_port, const char *name) {
     int ret = 0;
+
     if (!server_ip) {
-        struct pxenv_get_cached_info cachedinfo = { 0 };
-        cachedinfo.packet_type = 2;
-        pxe_call(PXENV_GET_CACHED_INFO, ((uint16_t)rm_seg(&cachedinfo)), (uint16_t)rm_off(&cachedinfo));
-        struct bootph *ph = (struct bootph*)(void *) (((((uint32_t)cachedinfo.buffer) >> 16) << 4) + (((uint32_t)cachedinfo.buffer) & 0xFFFF));
-        server_ip = ph->sip;
+        server_ip = get_boot_server_info();
     }
 
     struct PXENV_UNDI_GET_INFORMATION undi_info = { 0 };
@@ -35,10 +32,6 @@ int tftp_open(struct tftp_file_handle *handle, uint32_t server_ip, uint16_t serv
     //TODO figure out a more proper way to do this.
     uint16_t mtu = undi_info.MaxTranUnit - 48;
 
-    handle->server_ip = server_ip;
-    handle->server_port = server_port;
-    handle->packet_size = mtu;
-
     struct pxenv_get_file_size fsize = {
         .status = 0,
         .sip = server_ip,
@@ -49,63 +42,58 @@ int tftp_open(struct tftp_file_handle *handle, uint32_t server_ip, uint16_t serv
         return -1;
     }
 
-    handle->file_size = fsize.file_size;
+    handle->size = fsize.file_size;
+    handle->is_memfile = true;
 
-    volatile struct pxenv_open open = {
+    struct pxenv_open open = {
         .status = 0,
         .sip = server_ip,
         .port = (server_port) << 8,
         .packet_size = mtu
     };
     strcpy((char*)open.name, name);
+
     ret = pxe_call(TFTP_OPEN, ((uint16_t)rm_seg(&open)), (uint16_t)rm_off(&open));
     if (ret) {
         print("tftp: Failed to open file %x or bad packet size", open.status);
         return -1;
     }
+
     mtu = open.packet_size;
 
     uint8_t *buf = conv_mem_alloc(mtu);
-    handle->data = ext_mem_alloc(handle->file_size);
-    memset(handle->data, 0, handle->file_size);
-    size_t to_transfer = handle->file_size;
-    size_t progress = 0;
+    handle->fd = ext_mem_alloc(handle->size);
 
+    size_t progress = 0;
     bool slow = false;
 
-    while (to_transfer > 0) {
-        volatile struct pxenv_read read = {
+    while (progress < handle->size) {
+        struct pxenv_read read = {
             .boff = ((uint16_t)rm_off(buf)),
             .bseg = ((uint16_t)rm_seg(buf)),
         };
+
         ret = pxe_call(TFTP_READ, ((uint16_t)rm_seg(&read)), (uint16_t)rm_off(&read));
         if (ret) {
-            panic("failed reading");
+            panic("tftp: Read failure");
         }
-        memcpy(handle->data + progress, buf, read.bsize);
 
-        if (read.bsize < mtu && !slow) {
+        memcpy(handle->fd + progress, buf, read.bsize);
+
+        progress += read.bsize;
+
+        if (read.bsize < mtu && !slow && progress < handle->size) {
             slow = true;
             print("tftp: Server is sending the file in smaller packets (it sent %d bytes), download might take longer.\n", read.bsize);
         }
-        to_transfer -= read.bsize;
-        progress += read.bsize;
     }
 
     uint16_t close = 0;
     ret = pxe_call(TFTP_CLOSE, ((uint16_t)rm_seg(&close)), (uint16_t)rm_off(&close));
     if (ret) {
-        panic("close failed");
+        panic("tftp: Close failure");
     }
-    return 0;
-}
 
-int tftp_read(void* fd, void *buf, uint64_t loc, uint64_t count) {
-    struct tftp_file_handle *handle = (struct tftp_file_handle*)fd;
-    if ((loc + count) > handle->file_size) {
-        return -1;
-    }
-    memcpy(buf, handle->data + loc, count);
     return 0;
 }
 
tab: 248 wrap: offon