int cfe_vprintk(const char *fmt, va_list args) { static char buffer[1024]; static DEFINE_SPINLOCK(lock); static const char pfx[] = "CFE-console: "; static const size_t pfx_len = sizeof(pfx) - 1; unsigned long flags; int len, cnt, pos; int handle; int res; if (!cfe_present()) return -ENODEV; spin_lock_irqsave(&lock, flags); handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); if (CFE_ISERR(handle)) { len = -EIO; goto out; } strcpy(buffer, pfx); len = vscnprintf(buffer + pfx_len, sizeof(buffer) - pfx_len - 2, fmt, args); len += pfx_len; /* The CFE console requires CR-LF line-ends. * Add a CR, if we only terminate lines with a LF. * This does only fix CR-LF at the end of the string. * So for multiple lines, use multiple cfe_vprintk calls. */ if (len > 1 && buffer[len - 1] == '\n' && buffer[len - 2] != '\r') { buffer[len - 1] = '\r'; buffer[len] = '\n'; len += 1; } cnt = len; pos = 0; while (cnt > 0) { res = cfe_write(handle, buffer + pos, len - pos); if (CFE_ISERR(res)) { len = -EIO; goto out; } cnt -= res; pos += res; } out: spin_unlock_irqrestore(&lock, flags); return len; }
void __init cfe_die(char *fmt, ...) { char msg[128]; va_list ap; int handle; unsigned int count; va_start(ap, fmt); vsprintf(msg, fmt, ap); strcat(msg, "\r\n"); if (cfe_seal != CFE_EPTSEAL) goto no_cfe; /* disable XKS01 so that CFE can access the registers */ #if defined(CONFIG_BMIPS4380) __write_32bit_c0_register($22, 3, __read_32bit_c0_register($22, 3) & ~BIT(12)); #elif defined(CONFIG_BMIPS5000) __write_32bit_c0_register($22, 5, __read_32bit_c0_register($22, 5) & ~BIT(8)); #endif handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); if (handle < 0) goto no_cfe; cfe_write(handle, msg, strlen(msg)); for (count = 0; count < 0x7fffffff; count++) mb(); cfe_exit(0, 1); while (1) ; no_cfe: /* probably won't print anywhere useful */ printk(KERN_ERR "%s", msg); BUG(); va_end(ap); }
static void cfe_cnprobe(struct consdev *cp) { conhandle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); if (conhandle < 0) { cp->cn_pri = CN_DEAD; return; } /* XXX */ if (bootverbose) { char *bootmsg = "Using CFE firmware console.\n"; int i; for (i = 0; i < strlen(bootmsg); i++) cfe_cnputc(cp, bootmsg[i]); } cp->cn_pri = CN_LOW; }
static __init void prom_init_console(void) { /* Initialize CFE console */ cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); }
/* * prom_init is called just after the cpu type is determined, from setup_arch() */ void __init prom_init(void) { uint64_t cfe_ept, cfe_handle; unsigned int cfe_eptseal; int argc = fw_arg0; char **envp = (char **) fw_arg2; int *prom_vec = (int *) fw_arg3; _machine_restart = cfe_linux_restart; _machine_halt = cfe_linux_halt; _machine_power_off = cfe_linux_halt; /* * Check if a loader was used; if NOT, the 4 arguments are * what CFE gives us (handle, 0, EPT and EPTSEAL) */ if (argc < 0) { cfe_handle = (uint64_t)(long)argc; cfe_ept = (long)envp; cfe_eptseal = (uint32_t)(unsigned long)prom_vec; } else { if ((int32_t)(long)prom_vec < 0) { /* * Old loader; all it gives us is the handle, * so use the "known" entrypoint and assume * the seal. */ cfe_handle = (uint64_t)(long)prom_vec; cfe_ept = (uint64_t)((int32_t)0x9fc00500); cfe_eptseal = CFE_EPTSEAL; } else { /* * Newer loaders bundle the handle/ept/eptseal * Note: prom_vec is in the loader's useg * which is still alive in the TLB. */ cfe_handle = (uint64_t)((int32_t *)prom_vec)[0]; cfe_ept = (uint64_t)((int32_t *)prom_vec)[2]; cfe_eptseal = (unsigned int)((uint32_t *)prom_vec)[3]; } } if (cfe_eptseal != CFE_EPTSEAL) { /* too early for panic to do any good */ prom_printf("CFE's entrypoint seal doesn't match. Spinning."); while (1) ; } cfe_init(cfe_handle, cfe_ept); /* * Get the handle for (at least) prom_putchar, possibly for * boot console */ cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); if (cfe_getenv("LINUX_CMDLINE", arcs_cmdline, CL_SIZE) < 0) { if (argc < 0) { /* * It's OK for direct boot to not provide a * command line */ strcpy(arcs_cmdline, "root=/dev/ram0 "); #ifdef CONFIG_SIBYTE_PTSWARM strcat(arcs_cmdline, "console=ttyS0,115200 "); #endif } else { /* The loader should have set the command line */ /* too early for panic to do any good */ prom_printf("LINUX_CMDLINE not defined in cfe."); while (1) ; } } #ifdef CONFIG_BLK_DEV_INITRD { char *ptr; /* Need to find out early whether we've got an initrd. So scan the list looking now */ for (ptr = arcs_cmdline; *ptr; ptr++) { while (*ptr == ' ') { ptr++; } if (!strncmp(ptr, "initrd=", 7)) { initrd_setup(ptr+7); break; } else { while (*ptr && (*ptr != ' ')) { ptr++; } } } } #endif /* CONFIG_BLK_DEV_INITRD */ /* Not sure this is needed, but it's the safe way. */ arcs_cmdline[CL_SIZE-1] = 0; mips_machgroup = MACH_GROUP_SIBYTE; prom_meminit(); }
/** * Populate platform configuration data. */ static int bcm_init_platform_data(struct bcm_platform *bp) { bus_addr_t bus_addr, bus_size; bus_space_tag_t erom_bst; bus_space_handle_t erom_bsh; bool aob, pmu; int error; bus_addr = bcm_get_bus_addr(); bus_size = bcm_get_bus_size(); #ifdef CFE /* Fetch CFE console handle (if any). Must be initialized before * any calls to printf/early_putc. */ if ((bp->cfe_console = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE)) < 0) bp->cfe_console = -1; /* Probe CFE NVRAM sources */ bp->nvram_io = &bcm_cfe_nvram.io; error = bcm_nvram_find_cfedev(&bcm_cfe_nvram, &bp->nvram_cls); if (error) { bp->nvram_io = NULL; bp->nvram_cls = NULL; } #endif /* CFE */ /* Probe and attach device table provider, populating our * chip identification */ erom_bst = mips_bus_space_generic; erom_bsh = BCM_SOC_BSH(bus_addr, 0); error = bhnd_erom_iobus_init(&bp->erom_io, bus_addr, bus_size, erom_bst, erom_bsh); if (error) { BCM_ERR("failed to initialize erom I/O callbacks: %d\n", error); return (error); } error = bcm_erom_probe_and_attach(&bp->erom_impl, &bp->erom_ops, &bp->erom.obj, sizeof(bp->erom), &bp->erom_io.eio, &bp->cid); if (error) { BCM_ERR("error attaching erom parser: %d\n", error); bhnd_erom_io_fini(&bp->erom_io.eio); return (error); } if (bootverbose) bhnd_erom_dump(&bp->erom.obj); /* Fetch chipcommon core info */ error = bcm_find_core(bp, bcm_chipc_cores, nitems(bcm_chipc_cores), &bp->cc_id, &bp->cc_addr); if (error) { BCM_ERR("error locating chipc core: %d\n", error); return (error); } /* Fetch chipc capability flags */ bp->cc_caps = BCM_SOC_READ_4(bp->cc_addr, CHIPC_CAPABILITIES); bp->cc_caps_ext = 0x0; if (CHIPC_HWREV_HAS_CAP_EXT(bp->cc_id.hwrev)) bp->cc_caps_ext = BCM_CHIPC_READ_4(bp, CHIPC_CAPABILITIES_EXT); /* Fetch PMU info */ pmu = CHIPC_GET_FLAG(bp->cc_caps, CHIPC_CAP_PMU); aob = CHIPC_GET_FLAG(bp->cc_caps_ext, CHIPC_CAP2_AOB); if (pmu && aob) { /* PMU block mapped to a PMU core on the Always-on-Bus (aob) */ error = bcm_find_core(bp, bcm_pmu_cores, nitems(bcm_pmu_cores), &bp->pmu_id, &bp->pmu_addr); if (error) { BCM_ERR("error locating pmu core: %d\n", error); return (error); } } else if (pmu) { /* PMU block mapped to chipc */ bp->pmu_addr = bp->cc_addr; bp->pmu_id = bp->cc_id; } else { /* No PMU */ bp->pmu_addr = 0x0; memset(&bp->pmu_id, 0, sizeof(bp->pmu_id)); } /* Initialize PMU query state */ if (pmu) { error = bhnd_pmu_query_init(&bp->pmu, NULL, bp->cid, &bcm_pmu_soc_io, bp); if (error) { BCM_ERR("bhnd_pmu_query_init() failed: %d\n", error); return (error); } } /* Find CPU core info */ error = bcm_find_core(bp, bcm_cpu0_cores, nitems(bcm_cpu0_cores), &bp->cpu_id, &bp->cpu_addr); if (error) { BCM_ERR("error locating CPU core: %d\n", error); return (error); } /* Initialize our platform service registry */ if ((error = bhnd_service_registry_init(&bp->services))) { BCM_ERR("error initializing service registry: %d\n", error); return (error); } bcm_platform_data_avail = true; return (0); }
/* Initialize hardware. Called from crt0. */ void hardware_init_hook(void) { cfe_init (__cfe_handle, __cfe_entrypt); cfe_conshandle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); }
void cfe_open_console() { cfe_console_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); }