Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / sparc32 / boot.c
1 /*
2  *
3  */
4 #undef BOOTSTRAP
5 #include "config.h"
6 #include "libopenbios/bindings.h"
7 #include "arch/common/nvram.h"
8 #include "drivers/drivers.h"
9 #include "libc/diskio.h"
10 #include "libc/vsprintf.h"
11 #include "libopenbios/ofmem.h"
12 #include "libopenbios/sys_info.h"
13 #include "openprom.h"
14 #include "boot.h"
15 #include "context.h"
16
17 uint32_t kernel_image;
18 uint32_t kernel_size;
19 uint32_t qemu_cmdline;
20 uint32_t cmdline_size;
21 char boot_device;
22 const void *romvec;
23
24 static struct linux_mlist_v0 *totphyslist, *availlist, *prommaplist;
25
26 static void setup_romvec(void)
27 {
28         /* SPARC32 is slightly unusual in that before invoking any loaders, a romvec array
29            needs to be set up to pass certain parameters using a C struct. Hence this function
30            extracts the relevant boot information and places it in obp_arg. */
31
32         int intprop, proplen, target, device, i;
33         unsigned int *intprop_ptr;
34         phandle_t chosen;
35         char *prop, *id, *name;
36         static char bootpathbuf[128], bootargsbuf[128], buf[128];
37         struct linux_mlist_v0 **pp;
38
39         /* Get the stdin and stdout paths */
40         chosen = find_dev("/chosen");
41         intprop = get_int_property(chosen, "stdin", &proplen);
42         PUSH(intprop);
43         fword("get-instance-path");
44         ((struct linux_romvec *)romvec)->pv_stdin = pop_fstr_copy();
45
46         intprop = get_int_property(chosen, "stdout", &proplen);
47         PUSH(intprop);
48         fword("get-instance-path");
49         ((struct linux_romvec *)romvec)->pv_stdout = pop_fstr_copy();
50
51         /* Get the name of the selected boot device, along with the device and unit number */
52         prop = get_property(chosen, "bootpath", &proplen);
53         strncpy(bootpathbuf, prop, proplen);
54         prop = get_property(chosen, "bootargs", &proplen);
55         strncpy(bootargsbuf, prop, proplen);    
56
57         /* Set bootpath pointer used in romvec table to the bootpath */
58         push_str(bootpathbuf);
59         fword("pathres-resolve-aliases");
60         bootpath = pop_fstr_copy();
61         printk("bootpath: %s\n", bootpath);
62
63         /* Now do some work to get hold of the target, partition etc. */
64         push_str(bootpathbuf);
65         feval("open-dev");
66         feval("ihandle>boot-device-handle drop to my-self");
67         push_str("name");
68         fword("get-my-property");
69         POP();
70         name = pop_fstr_copy();
71
72         if (!strncmp(name, "sd", 2)) {
73
74                 /*
75                   Old-style SunOS disk paths are given in the form:
76
77                         sd(c,t,d):s
78
79                   where:
80                     c = controller (Nth controller in system, usually 0)
81                     t = target (my-unit phys.hi)
82                     d = device/LUN (my-unit phys.lo)
83                     s = slice/partition (my-args)
84                 */
85
86                 /* Controller currently always 0 */
87                 obp_arg.boot_dev_ctrl = 0;
88
89                 /* Get the target, device and slice */
90                 fword("my-unit");
91                 target = POP();
92                 device = POP();
93
94                 fword("my-args");
95                 id = pop_fstr_copy();
96
97                 if (id != NULL) {
98                         snprintf(buf, sizeof(buf), "sd(0,%d,%d):%c", target, device, id[0]);
99                         obp_arg.dev_partition = id[0] - 'a';
100                 } else {
101                         snprintf(buf, sizeof(buf), "sd(0,%d,%d)", target, device);
102                         obp_arg.dev_partition = 0;
103                 }
104
105                 obp_arg.boot_dev_unit = target;
106
107                 obp_arg.boot_dev[0] = buf[0];
108                 obp_arg.boot_dev[1] = buf[1];
109                 obp_arg.argv[0] = buf;
110                 obp_arg.argv[1] = bootargsbuf;
111
112         } else if (!strncmp(name, "SUNW,fdtwo", 10)) {
113                 
114                 obp_arg.boot_dev_ctrl = 0;
115                 obp_arg.boot_dev_unit = 0;
116                 obp_arg.dev_partition = 0;
117
118                 strcpy(buf, "fd()");
119
120                 obp_arg.boot_dev[0] = buf[0];
121                 obp_arg.boot_dev[1] = buf[1];
122                 obp_arg.argv[0] = buf;
123                 obp_arg.argv[1] = bootargsbuf;
124
125         } else if (!strncmp(name, "le", 2)) {
126
127                 obp_arg.boot_dev_ctrl = 0;
128                 obp_arg.boot_dev_unit = 0;
129                 obp_arg.dev_partition = 0;
130
131                 strcpy(buf, "le()");
132
133                 obp_arg.boot_dev[0] = buf[0];
134                 obp_arg.boot_dev[1] = buf[1];
135                 obp_arg.argv[0] = buf;
136                 obp_arg.argv[1] = bootargsbuf;
137
138         }
139
140         /* Generate the totphys (total memory available) list */
141         prop = get_property(s_phandle_memory, "reg", &proplen);
142         intprop_ptr = (unsigned int *)prop;
143
144         for (pp = &totphyslist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) {
145                 *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0));
146                 (**pp).theres_more = NULL;
147                 (**pp).start_adr = (char *)intprop_ptr[1];
148                 (**pp).num_bytes = intprop_ptr[2];
149
150                 intprop_ptr += 3;
151         }
152
153         /* Generate the avail (physical memory available) list */
154         prop = get_property(s_phandle_memory, "available", &proplen);
155         intprop_ptr = (unsigned int *)prop;
156
157         for (pp = &availlist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) {
158                 *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0));
159                 (**pp).theres_more = NULL;
160                 (**pp).start_adr = (char *)intprop_ptr[1];
161                 (**pp).num_bytes = intprop_ptr[2];
162
163                 intprop_ptr += 3;
164         }
165
166         /* Generate the prommap (taken virtual memory) list from inverse of available */
167         prop = get_property(s_phandle_mmu, "available", &proplen);
168         intprop_ptr = (unsigned int *)prop;
169
170         for (pp = &prommaplist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) {
171                 *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0));
172                 (**pp).theres_more = NULL;
173                 (**pp).start_adr = (char *)(intprop_ptr[1] + intprop_ptr[2]);
174
175                 if (i + 3 < (proplen / sizeof(int))) {
176                         /* Size from next entry */
177                         (**pp).num_bytes = (intprop_ptr[4] + intprop_ptr[5]) - (intprop_ptr[1] + intprop_ptr[2]);
178                 } else {
179                         /* Tail (size from top of virtual memory) */
180                         (**pp).num_bytes = 0xffffffffUL - (intprop_ptr[1] + intprop_ptr[2]) + 1;
181                 }
182
183                 intprop_ptr += 3;
184         }
185
186         /* Finally set the memory properties */
187         ((struct linux_romvec *)romvec)->pv_v0mem.v0_totphys = &totphyslist;
188         ((struct linux_romvec *)romvec)->pv_v0mem.v0_available = &availlist;
189         ((struct linux_romvec *)romvec)->pv_v0mem.v0_prommap = &prommaplist;
190 }
191
192
193 void go(void)
194 {
195         ucell address, type, size;
196         int image_retval = 0;
197
198         /* Get the entry point and the type (see forth/debugging/client.fs) */
199         feval("saved-program-state >sps.entry @");
200         address = POP();
201         feval("saved-program-state >sps.file-type @");
202         type = POP();
203         feval("saved-program-state >sps.file-size @");
204         size = POP();
205
206         setup_romvec();
207
208         printk("\nJumping to entry point " FMT_ucellx " for type " FMT_ucellx "...\n", address, type);
209
210         switch (type) {
211                 case 0x0:
212                         /* Start ELF boot image */
213                         image_retval = start_elf((unsigned long)address,
214                                                  (unsigned long)romvec);
215
216                         break;
217
218                 case 0x1:
219                         /* Start ELF image */
220                         image_retval = start_elf((unsigned long)address,
221                                                  (unsigned long)romvec);
222
223                         break;
224
225                 case 0x5:
226                         /* Start a.out image */
227                         image_retval = start_elf((unsigned long)address,
228                                                  (unsigned long)romvec);
229
230                         break;
231
232                 case 0x10:
233                         /* Start Fcode image */
234                         printk("Evaluating FCode...\n");
235                         PUSH(address);
236                         PUSH(1);
237                         fword("byte-load");
238                         image_retval = 0;
239                         break;
240
241                 case 0x11:
242                         /* Start Forth image */
243                         PUSH(address);
244                         PUSH(size);
245                         fword("eval2");
246                         image_retval = 0;
247                         break;
248         }
249
250         printk("Image returned with return value %#x\n", image_retval);
251 }
252
253
254 void boot(void)
255 {
256         /* Boot preloaded kernel */
257         if (kernel_size) {
258             printk("[sparc] Kernel already loaded\n");
259             start_elf(kernel_image, (unsigned long)romvec);
260         }
261 }