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