|
|
1.1 root 1: /* tag: openbios forth environment, executable code
2: *
3: * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
4: *
5: * See the file "COPYING" for further information about
6: * the copyright and warranty status of this work.
7: */
8:
9: #include "config.h"
10: #include "libopenbios/openbios.h"
11: #include "libopenbios/bindings.h"
12: #include "drivers/drivers.h"
13: #include "dict.h"
14: #include "arch/common/nvram.h"
15: #include "packages/nvram.h"
16: #include "libopenbios/sys_info.h"
17: #include "openbios.h"
18: #include "drivers/pci.h"
19: #include "asm/pci.h"
20: #include "boot.h"
21: #include "../../drivers/timer.h" // XXX
22: #define NO_QEMU_PROTOS
23: #include "arch/common/fw_cfg.h"
24: #include "libopenbios/ofmem.h"
25:
26: #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
27:
28: #define NVRAM_ADDR_LO 0x74
29: #define NVRAM_ADDR_HI 0x75
30: #define NVRAM_DATA 0x77
31:
32: #define APB_SPECIAL_BASE 0x1fe00000000ULL
33: #define APB_MEM_BASE 0x1ff00000000ULL
34:
35: #define MEMORY_SIZE (512*1024) /* 512K ram for hosted system */
36:
37: static ucell *memory;
38:
39: // XXX
40: #define NVRAM_SIZE 0x2000
41: #define NVRAM_IDPROM 0x1fd8
42: #define NVRAM_IDPROM_SIZE 32
43: #define NVRAM_OB_START (0)
44: #define NVRAM_OB_SIZE ((0x1fd0 - NVRAM_OB_START) & ~15)
45:
46: #define OBIO_CMDLINE_MAX 256
47: static char obio_cmdline[OBIO_CMDLINE_MAX];
48:
49: static uint8_t idprom[NVRAM_IDPROM_SIZE];
50:
51: struct hwdef {
52: pci_arch_t pci;
53: uint16_t machine_id_low, machine_id_high;
54: };
55:
56: static const struct hwdef hwdefs[] = {
57: {
58: .pci = {
59: .name = "SUNW,sabre",
60: .vendor_id = PCI_VENDOR_ID_SUN,
61: .device_id = PCI_DEVICE_ID_SUN_SABRE,
62: .cfg_addr = APB_SPECIAL_BASE + 0x1000000ULL, // PCI bus configuration space
63: .cfg_data = APB_MEM_BASE, // PCI bus memory space
64: .cfg_base = APB_SPECIAL_BASE,
65: .cfg_len = 0x2000000,
66: .host_mem_base = APB_MEM_BASE,
67: .pci_mem_base = 0,
68: .mem_len = 0x10000000,
69: .io_base = APB_SPECIAL_BASE + 0x2000000ULL, // PCI Bus I/O space
70: .io_len = 0x10000,
71: .irqs = { 0, 1, 2, 3 },
72: },
73: .machine_id_low = 0,
74: .machine_id_high = 255,
75: },
76: };
77:
78: struct cpudef {
79: unsigned long iu_version;
80: const char *name;
81: unsigned long ecache_associativity;
82: unsigned long ecache_line_size;
83: unsigned long ecache_size;
84: unsigned long num_dtlb_entries;
85: unsigned long dcache_associativity;
86: unsigned long dcache_line_size;
87: unsigned long dcache_size;
88: unsigned long num_itlb_entries;
89: unsigned long icache_associativity;
90: unsigned long icache_line_size;
91: unsigned long icache_size;
92: };
93:
94: /*
95: ( addr -- ? )
96: */
97: static void
98: set_trap_table(void)
99: {
100: unsigned long addr;
101:
102: addr = POP();
103: asm("wrpr %0, %%tba\n"
104: : : "r" (addr));
105: }
106:
107: /* Reset control register is defined in 17.2.7.3 of US IIi User Manual */
108: static void
109: sparc64_reset_all(void)
110: {
111: unsigned long addr = 0x1fe0000f020ULL;
112: unsigned long val = 1 << 29;
113:
114: asm("stxa %0, [%1] 0x15\n\t"
115: : : "r" (val), "r" (addr) : "memory");
116: }
117:
118: static void cpu_generic_init(const struct cpudef *cpu, uint32_t clock_frequency)
119: {
120: unsigned long iu_version;
121:
122: push_str("/");
123: fword("find-device");
124:
125: fword("new-device");
126:
127: push_str(cpu->name);
128: fword("device-name");
129:
130: push_str("cpu");
131: fword("device-type");
132:
133: asm("rdpr %%ver, %0\n"
134: : "=r"(iu_version) :);
135:
136: PUSH((iu_version >> 48) & 0xff);
137: fword("encode-int");
138: push_str("manufacturer#");
139: fword("property");
140:
141: PUSH((iu_version >> 32) & 0xff);
142: fword("encode-int");
143: push_str("implementation#");
144: fword("property");
145:
146: PUSH((iu_version >> 24) & 0xff);
147: fword("encode-int");
148: push_str("mask#");
149: fword("property");
150:
151: PUSH(9);
152: fword("encode-int");
153: push_str("sparc-version");
154: fword("property");
155:
156: PUSH(0);
157: fword("encode-int");
158: push_str("cpuid");
159: fword("property");
160:
161: PUSH(0);
162: fword("encode-int");
163: push_str("upa-portid");
164: fword("property");
165:
166: PUSH(clock_frequency);
167: fword("encode-int");
168: push_str("clock-frequency");
169: fword("property");
170:
171: PUSH(cpu->ecache_associativity);
172: fword("encode-int");
173: push_str("ecache-associativity");
174: fword("property");
175:
176: PUSH(cpu->ecache_line_size);
177: fword("encode-int");
178: push_str("ecache-line-size");
179: fword("property");
180:
181: PUSH(cpu->ecache_size);
182: fword("encode-int");
183: push_str("ecache-size");
184: fword("property");
185:
186: PUSH(cpu->dcache_associativity);
187: fword("encode-int");
188: push_str("dcache-associativity");
189: fword("property");
190:
191: PUSH(cpu->dcache_line_size);
192: fword("encode-int");
193: push_str("dcache-line-size");
194: fword("property");
195:
196: PUSH(cpu->dcache_size);
197: fword("encode-int");
198: push_str("dcache-size");
199: fword("property");
200:
201: PUSH(cpu->icache_associativity);
202: fword("encode-int");
203: push_str("icache-associativity");
204: fword("property");
205:
206: PUSH(cpu->ecache_line_size);
207: fword("encode-int");
208: push_str("icache-line-size");
209: fword("property");
210:
211: PUSH(cpu->ecache_size);
212: fword("encode-int");
213: push_str("icache-size");
214: fword("property");
215:
216: PUSH(cpu->num_itlb_entries);
217: fword("encode-int");
218: push_str("#itlb-entries");
219: fword("property");
220:
221: PUSH(cpu->num_dtlb_entries);
222: fword("encode-int");
223: push_str("#dtlb-entries");
224: fword("property");
225:
226: fword("finish-device");
227:
228: // Trap table
229: push_str("/openprom/client-services");
230: fword("find-device");
231: bind_func("SUNW,set-trap-table", set_trap_table);
232:
233: // Reset
234: bind_func("sparc64-reset-all", sparc64_reset_all);
235: push_str("' sparc64-reset-all to reset-all");
236: fword("eval");
237: }
238:
239: static const struct cpudef sparc_defs[] = {
240: {
241: .iu_version = (0x04ULL << 48) | (0x02ULL << 32),
242: .name = "FJSV,GP",
243: },
244: {
245: .iu_version = (0x04ULL << 48) | (0x03ULL << 32),
246: .name = "FJSV,GPUSK",
247: },
248: {
249: .iu_version = (0x04ULL << 48) | (0x04ULL << 32),
250: .name = "FJSV,GPUSC",
251: },
252: {
253: .iu_version = (0x04ULL << 48) | (0x05ULL << 32),
254: .name = "FJSV,GPUZC",
255: },
256: {
257: .iu_version = (0x17ULL << 48) | (0x10ULL << 32),
258: .name = "SUNW,UltraSPARC",
259: .ecache_associativity = 1, .ecache_line_size = 0x40, .ecache_size = 0x100000,
260: .dcache_associativity = 1, .dcache_line_size = 0x20, .dcache_size = 0x4000,
261: .icache_associativity = 2, .icache_line_size = 0x20, .icache_size = 0x4000,
262: .num_dtlb_entries = 0x40, .num_itlb_entries = 0x40,
263: },
264: {
265: .iu_version = (0x17ULL << 48) | (0x11ULL << 32),
266: .name = "SUNW,UltraSPARC-II",
267: .ecache_associativity = 1, .ecache_line_size = 0x40, .ecache_size = 0x100000,
268: .dcache_associativity = 1, .dcache_line_size = 0x20, .dcache_size = 0x4000,
269: .icache_associativity = 2, .icache_line_size = 0x20, .icache_size = 0x4000,
270: .num_dtlb_entries = 0x40, .num_itlb_entries = 0x40,
271: },
272: {
273: .iu_version = (0x17ULL << 48) | (0x12ULL << 32),
274: .name = "SUNW,UltraSPARC-IIi",
275: .ecache_associativity = 1, .ecache_line_size = 0x40, .ecache_size = 0x40000,
276: .dcache_associativity = 1, .dcache_line_size = 0x20, .dcache_size = 0x4000,
277: .icache_associativity = 2, .icache_line_size = 0x20, .icache_size = 0x4000,
278: .num_dtlb_entries = 0x40, .num_itlb_entries = 0x40,
279: },
280: {
281: .iu_version = (0x17ULL << 48) | (0x13ULL << 32),
282: .name = "SUNW,UltraSPARC-IIe",
283: },
284: {
285: .iu_version = (0x3eULL << 48) | (0x14ULL << 32),
286: .name = "SUNW,UltraSPARC-III",
287: },
288: {
289: .iu_version = (0x3eULL << 48) | (0x15ULL << 32),
290: .name = "SUNW,UltraSPARC-III+",
291: },
292: {
293: .iu_version = (0x3eULL << 48) | (0x16ULL << 32),
294: .name = "SUNW,UltraSPARC-IIIi",
295: },
296: {
297: .iu_version = (0x3eULL << 48) | (0x18ULL << 32),
298: .name = "SUNW,UltraSPARC-IV",
299: },
300: {
301: .iu_version = (0x3eULL << 48) | (0x19ULL << 32),
302: .name = "SUNW,UltraSPARC-IV+",
303: },
304: {
305: .iu_version = (0x3eULL << 48) | (0x22ULL << 32),
306: .name = "SUNW,UltraSPARC-IIIi+",
307: },
308: {
309: .iu_version = (0x3eULL << 48) | (0x23ULL << 32),
310: .name = "SUNW,UltraSPARC-T1",
311: },
312: {
313: .iu_version = (0x3eULL << 48) | (0x24ULL << 32),
314: .name = "SUNW,UltraSPARC-T2",
315: },
316: {
317: .iu_version = (0x22ULL << 48) | (0x10ULL << 32),
318: .name = "SUNW,UltraSPARC",
319: },
320: };
321:
322: static const struct cpudef *
323: id_cpu(void)
324: {
325: unsigned long iu_version;
326: unsigned int i;
327:
328: asm("rdpr %%ver, %0\n"
329: : "=r"(iu_version) :);
330: iu_version &= 0xffffffff00000000ULL;
331:
332: for (i = 0; i < sizeof(sparc_defs)/sizeof(struct cpudef); i++) {
333: if (iu_version == sparc_defs[i].iu_version)
334: return &sparc_defs[i];
335: }
336: printk("Unknown cpu (psr %lx), freezing!\n", iu_version);
337: for (;;);
338: }
339:
340: static uint8_t nvram_read_byte(uint16_t offset)
341: {
342: outb(offset & 0xff, NVRAM_ADDR_LO);
343: outb(offset >> 8, NVRAM_ADDR_HI);
344: return inb(NVRAM_DATA);
345: }
346:
347: static void nvram_read(uint16_t offset, char *buf, unsigned int nbytes)
348: {
349: unsigned int i;
350:
351: for (i = 0; i < nbytes; i++)
352: buf[i] = nvram_read_byte(offset + i);
353: }
354:
355: static void nvram_write_byte(uint16_t offset, uint8_t val)
356: {
357: outb(offset & 0xff, NVRAM_ADDR_LO);
358: outb(offset >> 8, NVRAM_ADDR_HI);
359: outb(val, NVRAM_DATA);
360: }
361:
362: static void nvram_write(uint16_t offset, const char *buf, unsigned int nbytes)
363: {
364: unsigned int i;
365:
366: for (i = 0; i < nbytes; i++)
367: nvram_write_byte(offset + i, buf[i]);
368: }
369:
370: static uint8_t qemu_uuid[16];
371:
372: void arch_nvram_get(char *data)
373: {
374: uint32_t size = 0;
375: const struct cpudef *cpu;
376: char buf[256];
377: uint32_t temp;
378: uint64_t ram_size;
379: uint32_t clock_frequency;
380: uint16_t machine_id;
381: const char *stdin_path, *stdout_path;
382:
383: fw_cfg_init();
384:
385: fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
386: buf[4] = '\0';
387:
388: printk("Configuration device id %s", buf);
389:
390: temp = fw_cfg_read_i32(FW_CFG_ID);
391: machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
392:
393: printk(" version %d machine id %d\n", temp, machine_id);
394:
395: if (temp != 1) {
396: printk("Incompatible configuration device version, freezing\n");
397: for(;;);
398: }
399:
400: kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE);
401: if (kernel_size)
402: kernel_image = fw_cfg_read_i64(FW_CFG_KERNEL_ADDR);
403:
404: size = fw_cfg_read_i32(FW_CFG_CMDLINE_SIZE);
405: if (size > OBIO_CMDLINE_MAX - 1)
406: size = OBIO_CMDLINE_MAX - 1;
407: if (size) {
408: fw_cfg_read(FW_CFG_CMDLINE_DATA, obio_cmdline, size);
409: }
410: obio_cmdline[size] = '\0';
411: qemu_cmdline = (uint64_t)obio_cmdline;
412: cmdline_size = size;
413: boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE);
414:
415: if (kernel_size)
416: printk("kernel addr %llx size %llx\n", kernel_image, kernel_size);
417: if (size)
418: printk("kernel cmdline %s\n", obio_cmdline);
419:
420: nvram_read(NVRAM_OB_START, data, NVRAM_OB_SIZE);
421:
422: temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
423:
424: printk("CPUs: %x", temp);
425:
426: clock_frequency = 100000000;
427:
428: cpu = id_cpu();
429: //cpu->initfn();
430: cpu_generic_init(cpu, clock_frequency);
431: printk(" x %s\n", cpu->name);
432:
433: // Add /uuid
434: fw_cfg_read(FW_CFG_UUID, (char *)qemu_uuid, 16);
435:
436: printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
437: qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
438: qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
439: qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
440: qemu_uuid[15]);
441:
442: push_str("/");
443: fword("find-device");
444:
445: PUSH((long)&qemu_uuid);
446: PUSH(16);
447: fword("encode-bytes");
448: push_str("uuid");
449: fword("property");
450:
451: // Add /idprom
452: nvram_read(NVRAM_IDPROM, (char *)idprom, NVRAM_IDPROM_SIZE);
453:
454: PUSH((long)&idprom);
455: PUSH(32);
456: fword("encode-bytes");
457: push_str("idprom");
458: fword("property");
459:
460: PUSH(500 * 1000 * 1000);
461: fword("encode-int");
462: push_str("clock-frequency");
463: fword("property");
464:
465: ram_size = fw_cfg_read_i64(FW_CFG_RAM_SIZE);
466:
467: ob_mmu_init(cpu->name, ram_size);
468:
469: /* Setup nvram variables */
470: push_str("/options");
471: fword("find-device");
472:
473: switch (boot_device) {
474: case 'a':
475: push_str("/obio/SUNW,fdtwo");
476: break;
477: case 'c':
478: push_str("disk:a");
479: break;
480: default:
481: case 'd':
482: push_str("cdrom:f cdrom");
483: break;
484: case 'n':
485: push_str("net");
486: break;
487: }
488:
489: fword("encode-string");
490: push_str("boot-device");
491: fword("property");
492:
493: push_str(obio_cmdline);
494: fword("encode-string");
495: push_str("boot-file");
496: fword("property");
497:
498: /* Set up other properties */
499: push_str("/chosen");
500: fword("find-device");
501:
502: if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) {
503: stdin_path = stdout_path = "ttya";
504: } else {
505: stdin_path = "keyboard";
506: stdout_path = "screen";
507: }
508:
509: push_str(stdin_path);
510: fword("open-dev");
511: fword("encode-int");
512: push_str("stdin");
513: fword("property");
514:
515: push_str(stdout_path);
516: fword("open-dev");
517: fword("encode-int");
518: push_str("stdout");
519: fword("property");
520:
521: push_str(stdin_path);
522: push_str("input-device");
523: fword("$setenv");
524:
525: push_str(stdout_path);
526: push_str("output-device");
527: fword("$setenv");
528:
529: push_str(stdin_path);
530: fword("input");
531:
532: push_str(stdout_path);
533: fword("output");
534: }
535:
536: void arch_nvram_put(char *data)
537: {
538: nvram_write(0, data, NVRAM_OB_SIZE);
539: }
540:
541: int arch_nvram_size(void)
542: {
543: return NVRAM_OB_SIZE;
544: }
545:
546: void setup_timers(void)
547: {
548: }
549:
550: void udelay(unsigned int usecs)
551: {
552: }
553:
554: static void init_memory(void)
555: {
556: memory = malloc(MEMORY_SIZE);
557: if (!memory)
558: printk("panic: not enough memory on host system.\n");
559:
560: /* we push start and end of memory to the stack
561: * so that it can be used by the forth word QUIT
562: * to initialize the memory allocator
563: */
564:
565: PUSH((ucell)memory);
566: PUSH((ucell)memory + (ucell)MEMORY_SIZE);
567: }
568:
569: static void
570: arch_init( void )
571: {
572: openbios_init();
573: modules_init();
574: #ifdef CONFIG_DRIVER_PCI
575: ob_pci_init();
576: #endif
577: nvconf_init();
578: device_end();
579:
580: bind_func("platform-boot", boot );
581: bind_func("(go)", go);
582: }
583:
584: unsigned long isa_io_base;
585:
586: int openbios(void)
587: {
588: unsigned int i;
589: uint16_t machine_id;
590: const struct hwdef *hwdef = NULL;
591:
592:
593: for (i = 0; i < sizeof(hwdefs) / sizeof(struct hwdef); i++) {
594: isa_io_base = hwdefs[i].pci.io_base;
595: machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
596: if (hwdefs[i].machine_id_low <= machine_id &&
597: hwdefs[i].machine_id_high >= machine_id) {
598: hwdef = &hwdefs[i];
599: arch = &hwdefs[i].pci;
600: break;
601: }
602: }
603: if (!hwdef)
604: for(;;); // Internal inconsistency, hang
605:
606: #ifdef CONFIG_DEBUG_CONSOLE
607: #ifdef CONFIG_DEBUG_CONSOLE_SERIAL
608: uart_init(CONFIG_SERIAL_PORT, CONFIG_SERIAL_SPEED);
609: #endif
610: /* Clear the screen. */
611: cls();
612: printk("OpenBIOS for Sparc64\n");
613: #endif
614:
615: ofmem_init();
616:
617: collect_sys_info(&sys_info);
618:
619: dict = (unsigned char *)sys_info.dict_start;
620: dicthead = (cell)sys_info.dict_end;
621: last = sys_info.dict_last;
622: dictlimit = sys_info.dict_limit;
623:
624: forth_init();
625:
626: #ifdef CONFIG_DEBUG_BOOT
627: printk("forth started.\n");
628: printk("initializing memory...");
629: #endif
630:
631: init_memory();
632:
633: #ifdef CONFIG_DEBUG_BOOT
634: printk("done\n");
635: #endif
636:
637: PUSH_xt( bind_noname_func(arch_init) );
638: fword("PREPOST-initializer");
639:
640: PC = (ucell)findword("initialize-of");
641:
642: if (!PC) {
643: printk("panic: no dictionary entry point.\n");
644: return -1;
645: }
646: #ifdef CONFIG_DEBUG_DICTIONARY
647: printk("done (%d bytes).\n", dicthead);
648: printk("Jumping to dictionary...\n");
649: #endif
650:
651: enterforth((xt_t)PC);
652: printk("falling off...\n");
653: free(dict);
654: return 0;
655: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.