| /* |
| * PReP boot partition loader |
| * Written by Mark Cave-Ayland 2018 |
| */ |
| |
| #include "config.h" |
| #include "kernel/kernel.h" |
| #include "libopenbios/bindings.h" |
| #include "libopenbios/prep_load.h" |
| #include "libopenbios/initprogram.h" |
| #include "libopenbios/sys_info.h" |
| #include "libc/byteorder.h" |
| #include "libc/diskio.h" |
| #include "drivers/drivers.h" |
| #define printf printk |
| #define debug printk |
| |
| |
| int |
| prep_load(ihandle_t dev) |
| { |
| int retval = LOADER_NOT_SUPPORT, fd, count, size; |
| ucell *loadbase; |
| unsigned char *image; |
| uint32_t entry_point_offset, load_image_length; |
| unsigned long entry; |
| |
| /* Mark the saved-program-state as invalid */ |
| feval("0 state-valid !"); |
| |
| fd = open_ih(dev); |
| if (fd == -1) { |
| goto out; |
| } |
| |
| /* Default to loading at load-base */ |
| fword("load-base"); |
| loadbase = cell2pointer(POP()); |
| |
| /* Read block 2 containing the boot info */ |
| seek_io(fd, 512); |
| count = read_io(fd, (void *)loadbase, 512); |
| if (count != 512) { |
| goto out; |
| } |
| |
| entry_point_offset = __le32_to_cpu(loadbase[0]); |
| load_image_length = __le32_to_cpu(loadbase[1]); |
| |
| /* Load the entire image */ |
| size = 0; |
| image = (unsigned char *)loadbase; |
| entry = (uintptr_t)loadbase + entry_point_offset; |
| |
| seek_io(fd, 0); |
| while (size < load_image_length) { |
| count = read_io(fd, (void *)image, 512); |
| if (count == -1) { |
| break; |
| } |
| |
| size += count; |
| image += count; |
| } |
| |
| /* If we didn't read anything, something went wrong */ |
| if (!size) { |
| goto out; |
| } |
| |
| /* Set correct size */ |
| size = load_image_length; |
| |
| /* Initialise load-state */ |
| PUSH(entry); |
| feval("load-state >ls.entry !"); |
| PUSH(size); |
| feval("load-state >ls.file-size !"); |
| feval("prep load-state >ls.file-type !"); |
| |
| out: |
| close_io(fd); |
| return retval; |
| } |
| |
| int |
| is_prep(char *addr) |
| { |
| /* PReP bootloaders are executed directly. So we'll say that something is |
| * PReP if the loader detected the PReP type sucessfully */ |
| ucell filetype; |
| |
| feval("load-state >ls.file-type @"); |
| filetype = POP(); |
| |
| return (filetype == 0x13); |
| } |
| |
| void |
| prep_init_program(void) |
| { |
| /* Entry point is already set, just need to setup the context */ |
| arch_init_program(); |
| |
| feval("-1 state-valid !"); |
| } |