mirror of
https://github.com/limine-bootloader/limine
synced 2024-12-12 09:44:04 +03:00
tftp: Overhaul and bug fixes
This commit is contained in:
parent
294382e3bf
commit
5f1c34a587
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user