X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=qemu%2Froms%2FSLOF%2Fboard-qemu%2Fllfw%2Fstage2.c;fp=qemu%2Froms%2FSLOF%2Fboard-qemu%2Fllfw%2Fstage2.c;h=ef6ea355a2689ca9a9e94080f89fb1a022f16527;hb=e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb;hp=0000000000000000000000000000000000000000;hpb=9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00;p=kvmfornfv.git diff --git a/qemu/roms/SLOF/board-qemu/llfw/stage2.c b/qemu/roms/SLOF/board-qemu/llfw/stage2.c new file mode 100644 index 000000000..ef6ea355a --- /dev/null +++ b/qemu/roms/SLOF/board-qemu/llfw/stage2.c @@ -0,0 +1,205 @@ +/****************************************************************************** + * Copyright (c) 2004, 2011 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include "memmap.h" +#include "stage2.h" +#include +#include "product.h" +#include "calculatecrc.h" +#include +#include +#include +#include "../lib/libhvcall/libhvcall.h" + +#define DEBUG(fmt...) +//#define DEBUG(fmt...) printf(fmt) + +uint64_t gVecNum; + +uint64_t exception_stack_frame; + +typedef void (*pInterruptFunc_t) (void); + +pInterruptFunc_t vectorTable[0x2E << 1]; + +extern void proceedInterrupt(void); + +/* Prototypes for functions of this file */ +void c_interrupt(uint64_t vecNum); +void set_exceptionVector(int num, void *func); +void early_c_entry(uint64_t start_addr, uint64_t fdt_addr); + + +static void exception_forward(void) +{ + uint64_t val; + + if (*(uint64_t *) XVECT_M_HANDLER) { + proceedInterrupt(); + } + + printf("\r\n exception %llx ", gVecNum); + asm volatile ("mfsrr0 %0":"=r" (val):); + printf("\r\nSRR0 = %08llx%08llx ", val >> 32, val); + asm volatile ("mfsrr1 %0":"=r" (val):); + printf(" SRR1 = %08llx%08llx ", val >> 32, val); + + asm volatile ("mfsprg %0,2":"=r" (val):); + printf("\r\nSPRG2 = %08llx%08llx ", val >> 32, val); + asm volatile ("mfsprg %0,3":"=r" (val):); + printf(" SPRG3 = %08llx%08llx \r\n", val >> 32, val); + while (1); +} + +void c_interrupt(uint64_t vecNum) +{ + gVecNum = vecNum; + if (vectorTable[vecNum >> 7]) { + vectorTable[vecNum >> 7] (); + } else { + exception_forward(); + } +} + +void set_exceptionVector(int num, void *func) +{ + vectorTable[num >> 7] = (pInterruptFunc_t) func; +} + +static void load_file(uint64_t destAddr, char *name, uint64_t maxSize, + uint64_t romfs_base) +{ + uint64_t cnt; + struct romfs_lookup_t fileInfo; + int rc; + + rc = c_romfs_lookup(name, romfs_base, &fileInfo); + if (rc) { + printf("Cannot find romfs file %s\n", name); + return; + } + DEBUG("Found romfs file %s\n", name); + if (maxSize) { + cnt = maxSize; + } else { + cnt = fileInfo.size_data; + } + memcpy((void *)destAddr, (void *)fileInfo.addr_data, cnt); + flush_cache((void *) destAddr, fileInfo.size_data); +} + +extern void print_version(void); + +/*************************************************************************** + * Function: early_c_entry + * Input : start_addr + * + * Description: + **************************************************************************/ +void early_c_entry(uint64_t start_addr, uint64_t fdt_addr) +{ + struct romfs_lookup_t fileInfo; + void (*ofw_start) (uint64_t, uint64_t, uint64_t, uint64_t, uint64_t); + uint64_t *boot_info; + uint64_t romfs_base, paflof_base; + // romfs header values + // struct stH *header = (struct stH *) (start_addr + 0x28); + // uint64_t flashlen = header->flashlen; + unsigned long ofw_addr[2]; + int rc; + extern char __executable_start; + extern char __etext; + + /* + * If we run on a broken environment, we need to patch our own sc 1 + * calls to be able to trap hypercalls. This does not cover RTAS or + * any payload we will load yet. + */ + if (patch_broken_sc1(&__executable_start, &__etext, NULL)) { + /* We are running in PR KVM on top of pHyp. Print all output + we missed to print so far again to fake identical behavior */ + printf("\n\r\nSLOF"); + print_version(); + } + + if (fdt_addr == 0) { + puts("ERROR: Flatten device tree not available!"); + } + + /* Hack: Determine base for "ROM filesystem" in memory... + * QEMU loads the FDT at the top of the available RAM, so we place + * the ROMFS just underneath. */ + romfs_base = (fdt_addr - 0x410000) & ~0xffffLL; + memcpy((char *)romfs_base, 0, 0x400000); + + exception_stack_frame = 0; + + printf(" Press \"s\" to enter Open Firmware.\r\n\r\n"); + + DEBUG(" [c_romfs_lookup at %p]\n", c_romfs_lookup); + rc = c_romfs_lookup("bootinfo", romfs_base, &fileInfo); + if (rc) + printf(" !!! roomfs lookup(bootinfo) = %d\n", rc); + boot_info = (uint64_t *) fileInfo.addr_data; + boot_info[1] = start_addr; + load_file(0x100, "xvect", 0, romfs_base); + rc = c_romfs_lookup("ofw_main", romfs_base, &fileInfo); + if (rc) + printf(" !!! roomfs lookup(bootinfo) = %d\n", rc); + + DEBUG(" [ofw_main addr hdr 0x%lx]\n", fileInfo.addr_header); + DEBUG(" [ofw_main addr data 0x%lx]\n", fileInfo.addr_data); + DEBUG(" [ofw_main size data 0x%lx]\n", fileInfo.size_data); + DEBUG(" [ofw_main flags 0x%lx]\n", fileInfo.flags); + DEBUG(" [hdr: 0x%08lx 0x%08lx]\n [ 0x%08lx 0x%08lx]\n", + ((uint64_t *)fileInfo.addr_header)[0], + ((uint64_t *)fileInfo.addr_header)[1], + ((uint64_t *)fileInfo.addr_header)[2], + ((uint64_t *)fileInfo.addr_header)[3]); + + /* Assume that paflof and SNK need ca. 31 MiB RAM right now. + * TODO: Use value from ELF file instead */ + paflof_base = romfs_base - 0x1F00000 + 0x100; + if ((int64_t)paflof_base <= 0LL) { + puts("ERROR: Not enough memory for Open Firmware"); + } + rc = elf_load_file_to_addr((void *)fileInfo.addr_data, (void*)paflof_base, + ofw_addr, NULL, flush_cache); + DEBUG(" [load_elf_file returned %d]\n", rc); + + ofw_start = + (void (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)) + &ofw_addr; + // re-enable the cursor + printf("%s%s", TERM_CTRL_RESET, TERM_CTRL_CRSON); + DEBUG(" [ofw_start=%p ofw_addr=0x%lx]\n", ofw_start, ofw_addr[0]); + ofw_addr[1] = ofw_addr[0]; + /* Call the Open Firmware layer with ePAPR-style calling conventions: + * r3 = R3 Effective address of the device tree image. Note: this + * address must be 8-byte aligned in memory. + * r4 = implementation dependent, we use it for ROMFS base address + * r5 = 0 + * r6 = 0x65504150 -- ePAPR magic value-to distinguish from + * non-ePAPR-compliant firmware + * r7 = size of Initially Mapped Area + * (right now we assume everything from 0 to the FDT is the IMA) + */ + asm volatile("isync; sync;" : : : "memory"); + ofw_start(fdt_addr, romfs_base, 0, 0x65504150, fdt_addr); + asm volatile("isync; sync;" : : : "memory"); + // never return +}