1 /*
2  * PReP boot partition loader
3  * Written by Mark Cave-Ayland 2018
4  */
5 
6 #include "config.h"
7 #include "kernel/kernel.h"
8 #include "libopenbios/bindings.h"
9 #include "libopenbios/prep_load.h"
10 #include "libopenbios/initprogram.h"
11 #include "libopenbios/sys_info.h"
12 #include "libc/byteorder.h"
13 #include "libc/diskio.h"
14 #include "drivers/drivers.h"
15 #define printf printk
16 #define debug printk
17 
18 
19 int
prep_load(ihandle_t dev)20 prep_load(ihandle_t dev)
21 {
22     int retval = LOADER_NOT_SUPPORT, fd, count, size;
23     ucell *loadbase;
24     unsigned char *image;
25     uint32_t entry_point_offset, load_image_length;
26     unsigned long entry;
27 
28     /* Mark the saved-program-state as invalid */
29     feval("0 state-valid !");
30 
31     fd = open_ih(dev);
32     if (fd == -1) {
33         goto out;
34     }
35 
36     /* Default to loading at load-base */
37     fword("load-base");
38     loadbase = cell2pointer(POP());
39 
40     /* Read block 2 containing the boot info */
41     seek_io(fd, 512);
42     count = read_io(fd, (void *)loadbase, 512);
43     if (count != 512) {
44         goto out;
45     }
46 
47     entry_point_offset = __le32_to_cpu(loadbase[0]);
48     load_image_length = __le32_to_cpu(loadbase[1]);
49 
50     /* Load the entire image */
51     size = 0;
52     image = (unsigned char *)loadbase;
53     entry = (uintptr_t)loadbase + entry_point_offset;
54 
55     seek_io(fd, 0);
56     while (size < load_image_length) {
57         count = read_io(fd, (void *)image, 512);
58         if (count == -1) {
59             break;
60         }
61 
62         size += count;
63         image += count;
64     }
65 
66     /* If we didn't read anything, something went wrong */
67     if (!size) {
68         goto out;
69     }
70 
71     /* Set correct size */
72     size = load_image_length;
73 
74     /* Initialise load-state */
75     PUSH(entry);
76     feval("load-state >ls.entry !");
77     PUSH(size);
78     feval("load-state >ls.file-size !");
79     feval("prep load-state >ls.file-type !");
80 
81 out:
82     close_io(fd);
83     return retval;
84 }
85 
86 int
is_prep(char * addr)87 is_prep(char *addr)
88 {
89     /* PReP bootloaders are executed directly. So we'll say that something is
90      * PReP if the loader detected the PReP type sucessfully */
91     ucell filetype;
92 
93     feval("load-state >ls.file-type @");
94     filetype = POP();
95 
96     return (filetype == 0x13);
97 }
98 
99 void
prep_init_program(void)100 prep_init_program(void)
101 {
102     /* Entry point is already set, just need to setup the context */
103     arch_init_program();
104 
105     feval("-1 state-valid !");
106 }
107