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