rulimine/stage23/pxe/tftp.s2.c

101 lines
2.7 KiB
C
Raw Normal View History

#if bios == 1
2021-03-02 12:23:43 +03:00
2020-11-05 03:37:45 +03:00
#include <pxe/tftp.h>
#include <pxe/pxe.h>
#include <lib/real.h>
#include <lib/print.h>
#include <lib/libc.h>
#include <mm/pmm.h>
#include <lib/blib.h>
2021-03-13 11:08:01 +03:00
uint32_t get_boot_server_info(void) {
2020-12-10 16:10:47 +03:00
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));
return ph->sip;
}
2021-08-12 08:40:29 +03:00
int tftp_open(struct file_handle *handle, uint32_t server_ip, uint16_t server_port, const char *name) {
2020-11-05 03:37:45 +03:00
int ret = 0;
2021-08-12 08:40:29 +03:00
2020-11-05 03:37:45 +03:00
if (!server_ip) {
2021-08-12 08:40:29 +03:00
server_ip = get_boot_server_info();
2020-11-05 03:37:45 +03:00
}
2021-03-02 12:23:43 +03:00
2020-11-05 03:37:45 +03:00
struct PXENV_UNDI_GET_INFORMATION undi_info = { 0 };
ret = pxe_call(UNDI_GET_INFORMATION, ((uint16_t)rm_seg(&undi_info)), (uint16_t)rm_off(&undi_info));
if (ret) {
return -1;
}
2021-03-02 12:23:43 +03:00
2020-11-05 03:37:45 +03:00
//TODO figure out a more proper way to do this.
uint16_t mtu = undi_info.MaxTranUnit - 48;
struct pxenv_get_file_size fsize = {
.status = 0,
.sip = server_ip,
};
strcpy((char*)fsize.name, name);
ret = pxe_call(TFTP_GET_FILE_SIZE, ((uint16_t)rm_seg(&fsize)), (uint16_t)rm_off(&fsize));
if (ret) {
return -1;
}
2021-08-12 08:40:29 +03:00
handle->size = fsize.file_size;
handle->is_memfile = true;
2020-11-05 03:37:45 +03:00
2021-08-12 08:40:29 +03:00
struct pxenv_open open = {
2020-11-05 03:37:45 +03:00
.status = 0,
.sip = server_ip,
.port = (server_port) << 8,
.packet_size = mtu
};
strcpy((char*)open.name, name);
2021-08-12 08:40:29 +03:00
2020-11-05 03:37:45 +03:00
ret = pxe_call(TFTP_OPEN, ((uint16_t)rm_seg(&open)), (uint16_t)rm_off(&open));
if (ret) {
2021-05-11 07:46:42 +03:00
print("tftp: Failed to open file %x or bad packet size", open.status);
2020-11-05 03:37:45 +03:00
return -1;
}
2021-08-12 08:40:29 +03:00
2020-11-05 03:37:45 +03:00
mtu = open.packet_size;
uint8_t *buf = conv_mem_alloc(mtu);
2021-08-12 08:40:29 +03:00
handle->fd = ext_mem_alloc(handle->size);
2020-11-05 03:37:45 +03:00
2021-08-12 08:40:29 +03:00
size_t progress = 0;
bool slow = false;
2021-08-12 08:40:29 +03:00
while (progress < handle->size) {
struct pxenv_read read = {
2020-11-05 03:37:45 +03:00
.boff = ((uint16_t)rm_off(buf)),
.bseg = ((uint16_t)rm_seg(buf)),
};
2021-08-12 08:40:29 +03:00
2020-11-05 03:37:45 +03:00
ret = pxe_call(TFTP_READ, ((uint16_t)rm_seg(&read)), (uint16_t)rm_off(&read));
if (ret) {
2021-08-12 08:40:29 +03:00
panic("tftp: Read failure");
2020-11-05 03:37:45 +03:00
}
2021-08-12 08:40:29 +03:00
memcpy(handle->fd + progress, buf, read.bsize);
progress += read.bsize;
if (read.bsize < mtu && !slow && progress < handle->size) {
slow = true;
2021-05-11 07:46:42 +03:00
print("tftp: Server is sending the file in smaller packets (it sent %d bytes), download might take longer.\n", read.bsize);
2020-11-05 03:37:45 +03:00
}
}
uint16_t close = 0;
ret = pxe_call(TFTP_CLOSE, ((uint16_t)rm_seg(&close)), (uint16_t)rm_off(&close));
if (ret) {
2021-08-12 08:40:29 +03:00
panic("tftp: Close failure");
2020-11-05 03:37:45 +03:00
}
return 0;
}
2021-03-02 12:23:43 +03:00
#endif