mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
Signed-off-by: Blue Swirl <blauwirbel@gmail.com> git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@844 f158a5a8-5612-0410-a976-696ce0be7e32
368 lines
9.1 KiB
C
368 lines
9.1 KiB
C
/* tag: openbios forth environment, executable code
|
|
*
|
|
* Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
|
|
*
|
|
* See the file "COPYING" for further information about
|
|
* the copyright and warranty status of this work.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "libopenbios/openbios.h"
|
|
#include "libopenbios/bindings.h"
|
|
#include "drivers/drivers.h"
|
|
#include "asm/types.h"
|
|
#include "dict.h"
|
|
#include "kernel/kernel.h"
|
|
#include "kernel/stack.h"
|
|
#include "arch/common/nvram.h"
|
|
#include "packages/nvram.h"
|
|
#include "../../drivers/timer.h" // XXX
|
|
#include "libopenbios/sys_info.h"
|
|
#include "openbios.h"
|
|
#include "boot.h"
|
|
#include "openprom.h"
|
|
#include "packages/video.h"
|
|
#define NO_QEMU_PROTOS
|
|
#include "arch/common/fw_cfg.h"
|
|
|
|
#define MEMORY_SIZE (128*1024) /* 16K ram for hosted system */
|
|
#define DICTIONARY_SIZE (256*1024) /* 256K for the dictionary */
|
|
#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
|
|
|
|
static ucell *memory;
|
|
|
|
int qemu_machine_type;
|
|
|
|
struct hwdef {
|
|
uint64_t iommu_base, slavio_base;
|
|
uint64_t intctl_base, counter_base, nvram_base, ms_kb_base, serial_base;
|
|
unsigned long fd_offset, counter_offset, intr_offset;
|
|
unsigned long aux1_offset, aux2_offset;
|
|
uint64_t dma_base, esp_base, le_base;
|
|
uint64_t tcx_base;
|
|
int machine_id_low, machine_id_high;
|
|
};
|
|
|
|
static const struct hwdef hwdefs[] = {
|
|
/* SS-5 */
|
|
{
|
|
.iommu_base = 0x10000000,
|
|
.tcx_base = 0x50000000,
|
|
.slavio_base = 0x71000000,
|
|
.ms_kb_base = 0x71000000,
|
|
.serial_base = 0x71100000,
|
|
.nvram_base = 0x71200000,
|
|
.fd_offset = 0x00400000,
|
|
.counter_offset = 0x00d00000,
|
|
.intr_offset = 0x00e00000,
|
|
.aux1_offset = 0x00900000,
|
|
.aux2_offset = 0x00910000,
|
|
.dma_base = 0x78400000,
|
|
.esp_base = 0x78800000,
|
|
.le_base = 0x78c00000,
|
|
.machine_id_low = 32,
|
|
.machine_id_high = 63,
|
|
},
|
|
/* SS-10 */
|
|
{
|
|
.iommu_base = 0xfe0000000ULL,
|
|
.tcx_base = 0xe20000000ULL,
|
|
.slavio_base = 0xff1000000ULL,
|
|
.ms_kb_base = 0xff1000000ULL,
|
|
.serial_base = 0xff1100000ULL,
|
|
.nvram_base = 0xff1200000ULL,
|
|
.fd_offset = 0x00700000, // 0xff1700000ULL,
|
|
.counter_offset = 0x00300000, // 0xff1300000ULL,
|
|
.intr_offset = 0x00400000, // 0xff1400000ULL,
|
|
.aux1_offset = 0x00800000, // 0xff1800000ULL,
|
|
.aux2_offset = 0x00a01000, // 0xff1a01000ULL,
|
|
.dma_base = 0xef0400000ULL,
|
|
.esp_base = 0xef0800000ULL,
|
|
.le_base = 0xef0c00000ULL,
|
|
.machine_id_low = 64,
|
|
.machine_id_high = 65,
|
|
},
|
|
/* SS-600MP */
|
|
{
|
|
.iommu_base = 0xfe0000000ULL,
|
|
.tcx_base = 0xe20000000ULL,
|
|
.slavio_base = 0xff1000000ULL,
|
|
.ms_kb_base = 0xff1000000ULL,
|
|
.serial_base = 0xff1100000ULL,
|
|
.nvram_base = 0xff1200000ULL,
|
|
.fd_offset = -1,
|
|
.counter_offset = 0x00300000, // 0xff1300000ULL,
|
|
.intr_offset = 0x00400000, // 0xff1400000ULL,
|
|
.aux1_offset = 0x00800000, // 0xff1800000ULL,
|
|
.aux2_offset = 0x00a01000, // 0xff1a01000ULL, XXX should not exist
|
|
.dma_base = 0xef0081000ULL,
|
|
.esp_base = 0xef0080000ULL,
|
|
.le_base = 0xef0060000ULL,
|
|
.machine_id_low = 66,
|
|
.machine_id_high = 66,
|
|
},
|
|
};
|
|
|
|
static const struct hwdef *hwdef;
|
|
|
|
void setup_timers(void)
|
|
{
|
|
}
|
|
|
|
void udelay(unsigned int usecs)
|
|
{
|
|
}
|
|
|
|
void mdelay(unsigned int msecs)
|
|
{
|
|
}
|
|
|
|
/* Add /uuid */
|
|
static void setup_uuid(void)
|
|
{
|
|
static uint8_t qemu_uuid[16];
|
|
|
|
fw_cfg_read(FW_CFG_UUID, (char *)qemu_uuid, 16);
|
|
|
|
printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
|
|
qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
|
|
qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
|
|
qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
|
|
qemu_uuid[15]);
|
|
|
|
push_str("/");
|
|
fword("find-device");
|
|
|
|
PUSH((long)&qemu_uuid);
|
|
PUSH(16);
|
|
fword("encode-bytes");
|
|
push_str("uuid");
|
|
fword("property");
|
|
}
|
|
|
|
static void setup_stdio(void)
|
|
{
|
|
char nographic;
|
|
const char *stdin, *stdout;
|
|
phandle_t chosen;
|
|
|
|
fw_cfg_read(FW_CFG_NOGRAPHIC, &nographic, 1);
|
|
if (nographic) {
|
|
obp_stdin = PROMDEV_TTYA;
|
|
obp_stdout = PROMDEV_TTYA;
|
|
stdin = "ttya";
|
|
stdout = "ttya";
|
|
} else {
|
|
obp_stdin = PROMDEV_KBD;
|
|
obp_stdout = PROMDEV_SCREEN;
|
|
stdin = "keyboard";
|
|
stdout = "screen";
|
|
}
|
|
|
|
push_str("/");
|
|
fword("find-device");
|
|
|
|
push_str(stdin);
|
|
fword("pathres-resolve-aliases");
|
|
fword("encode-string");
|
|
push_str("stdin-path");
|
|
fword("property");
|
|
|
|
push_str(stdout);
|
|
fword("pathres-resolve-aliases");
|
|
fword("encode-string");
|
|
push_str("stdout-path");
|
|
fword("property");
|
|
|
|
chosen = find_dev("/chosen");
|
|
push_str(stdin);
|
|
fword("open-dev");
|
|
set_int_property(chosen, "stdin", POP());
|
|
|
|
chosen = find_dev("/chosen");
|
|
push_str(stdout);
|
|
fword("open-dev");
|
|
set_int_property(chosen, "stdout", POP());
|
|
|
|
push_str(stdin);
|
|
push_str("input-device");
|
|
fword("$setenv");
|
|
|
|
push_str(stdout);
|
|
push_str("output-device");
|
|
fword("$setenv");
|
|
|
|
push_str(stdin);
|
|
fword("input");
|
|
|
|
obp_stdin_path = stdin;
|
|
obp_stdout_path = stdout;
|
|
}
|
|
|
|
static void init_memory(void)
|
|
{
|
|
memory = malloc(MEMORY_SIZE);
|
|
if (!memory)
|
|
printk("panic: not enough memory on host system.\n");
|
|
|
|
/* we push start and end of memory to the stack
|
|
* so that it can be used by the forth word QUIT
|
|
* to initialize the memory allocator
|
|
*/
|
|
|
|
PUSH((ucell)memory);
|
|
PUSH((ucell)memory + MEMORY_SIZE);
|
|
}
|
|
|
|
static void
|
|
arch_init( void )
|
|
{
|
|
static char cmdline[128];
|
|
int size = 0;
|
|
const char *kernel_cmdline;
|
|
|
|
openbios_init();
|
|
modules_init();
|
|
ob_init_mmu();
|
|
ob_init_iommu(hwdef->iommu_base);
|
|
#ifdef CONFIG_DRIVER_OBIO
|
|
ob_obio_init(hwdef->slavio_base, hwdef->fd_offset,
|
|
hwdef->counter_offset, hwdef->intr_offset,
|
|
hwdef->aux1_offset, hwdef->aux2_offset);
|
|
nvconf_init();
|
|
#endif
|
|
#ifdef CONFIG_DRIVER_SBUS
|
|
#ifdef CONFIG_DEBUG_CONSOLE_VIDEO
|
|
init_video((unsigned long)vmem, 1024, 768, 8, 1024);
|
|
#endif
|
|
ob_sbus_init(hwdef->iommu_base + 0x1000ULL, qemu_machine_type);
|
|
#endif
|
|
device_end();
|
|
|
|
setup_stdio();
|
|
/* Initialiase openprom romvec */
|
|
romvec = init_openprom();
|
|
|
|
kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE);
|
|
if (kernel_size)
|
|
kernel_image = fw_cfg_read_i32(FW_CFG_KERNEL_ADDR);
|
|
|
|
kernel_cmdline = (const char *) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE);
|
|
if (kernel_cmdline) {
|
|
size = strlen(kernel_cmdline);
|
|
memcpy(cmdline, kernel_cmdline, size);
|
|
obp_arg.argv[1] = cmdline;
|
|
}
|
|
cmdline[size] = '\0';
|
|
qemu_cmdline = (uint32_t)cmdline;
|
|
|
|
/* Setup nvram variables */
|
|
push_str("/options");
|
|
fword("find-device");
|
|
push_str(cmdline);
|
|
fword("encode-string");
|
|
push_str("boot-file");
|
|
fword("property");
|
|
|
|
boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE);
|
|
|
|
switch (boot_device) {
|
|
case 'a':
|
|
push_str("floppy");
|
|
break;
|
|
case 'c':
|
|
push_str("disk");
|
|
break;
|
|
default:
|
|
case 'd':
|
|
push_str("cdrom");
|
|
break;
|
|
case 'n':
|
|
push_str("net");
|
|
break;
|
|
}
|
|
|
|
fword("encode-string");
|
|
push_str("boot-device");
|
|
fword("property");
|
|
|
|
/* Set up other properties */
|
|
push_str("/chosen");
|
|
fword("find-device");
|
|
|
|
bind_func("platform-boot", boot );
|
|
bind_func("(go)", go );
|
|
|
|
setup_uuid();
|
|
}
|
|
|
|
int openbios(void)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < sizeof(hwdefs) / sizeof(struct hwdef); i++) {
|
|
if (hwdefs[i].machine_id_low <= qemu_machine_type &&
|
|
hwdefs[i].machine_id_high >= qemu_machine_type) {
|
|
hwdef = &hwdefs[i];
|
|
break;
|
|
}
|
|
}
|
|
if (!hwdef)
|
|
for(;;); // Internal inconsistency, hang
|
|
|
|
#ifdef CONFIG_DRIVER_SBUS
|
|
init_mmu_swift();
|
|
#endif
|
|
#ifdef CONFIG_DEBUG_CONSOLE
|
|
#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
|
|
uart_init(hwdef->serial_base | (CONFIG_SERIAL_PORT? 0ULL: 4ULL),
|
|
CONFIG_SERIAL_SPEED);
|
|
#endif
|
|
#ifdef CONFIG_DEBUG_CONSOLE_VIDEO
|
|
tcx_init(hwdef->tcx_base);
|
|
kbd_init(hwdef->ms_kb_base);
|
|
#endif
|
|
/* Clear the screen. */
|
|
cls();
|
|
#endif
|
|
|
|
collect_sys_info(&sys_info);
|
|
|
|
dict = malloc(DICTIONARY_SIZE);
|
|
dictlimit = DICTIONARY_SIZE;
|
|
|
|
load_dictionary((char *)sys_info.dict_start,
|
|
(unsigned long)sys_info.dict_end
|
|
- (unsigned long)sys_info.dict_start);
|
|
|
|
#ifdef CONFIG_DEBUG_BOOT
|
|
printk("forth started.\n");
|
|
printk("initializing memory...");
|
|
#endif
|
|
|
|
init_memory();
|
|
|
|
#ifdef CONFIG_DEBUG_BOOT
|
|
printk("done\n");
|
|
#endif
|
|
|
|
PUSH_xt( bind_noname_func(arch_init) );
|
|
fword("PREPOST-initializer");
|
|
|
|
PC = (ucell)findword("initialize-of");
|
|
|
|
if (!PC) {
|
|
printk("panic: no dictionary entry point.\n");
|
|
return -1;
|
|
}
|
|
#ifdef CONFIG_DEBUG_DICTIONARY
|
|
printk("done (%d bytes).\n", dicthead);
|
|
printk("Jumping to dictionary...\n");
|
|
#endif
|
|
|
|
enterforth((xt_t)PC);
|
|
|
|
free(dict);
|
|
return 0;
|
|
}
|