#include "fwcfg.h" #include "smp.h" #include "libcflat.h" static struct spinlock lock; static long fw_override[FW_CFG_NUM_ENTRIES]; static bool fw_override_done; bool no_test_device; static void read_cfg_override(void) { const char *str; int i; /* Initialize to negative value that would be considered as invalid */ for (i = 0; i < FW_CFG_NUM_ENTRIES; i++) fw_override[i] = -1; if ((str = getenv("NR_CPUS"))) fw_override[FW_CFG_NB_CPUS] = atol(str); /* MEMSIZE is in megabytes */ if ((str = getenv("MEMSIZE"))) fw_override[FW_CFG_RAM_SIZE] = atol(str) * 1024 * 1024; if ((str = getenv("TEST_DEVICE"))) no_test_device = !atol(str); if ((str = getenv("MEMLIMIT"))) fw_override[FW_CFG_MAX_RAM] = atol(str) * 1024 * 1024; fw_override_done = true; } static uint64_t fwcfg_get_u(uint16_t index, int bytes) { uint64_t r = 0; uint8_t b; int i; if (!fw_override_done) read_cfg_override(); if (index < FW_CFG_NUM_ENTRIES && fw_override[index] >= 0) return fw_override[index]; spin_lock(&lock); asm volatile ("out %0, %1" : : "a"(index), "d"((uint16_t)BIOS_CFG_IOPORT)); for (i = 0; i < bytes; ++i) { asm volatile ("in %1, %0" : "=a"(b) : "d"((uint16_t)(BIOS_CFG_IOPORT + 1))); r |= (uint64_t)b << (i * 8); } spin_unlock(&lock); return r; } uint8_t fwcfg_get_u8(unsigned index) { return fwcfg_get_u(index, 1); } uint16_t fwcfg_get_u16(unsigned index) { return fwcfg_get_u(index, 2); } uint32_t fwcfg_get_u32(unsigned index) { return fwcfg_get_u(index, 4); } uint64_t fwcfg_get_u64(unsigned index) { return fwcfg_get_u(index, 8); } unsigned fwcfg_get_nb_cpus(void) { return fwcfg_get_u16(FW_CFG_NB_CPUS); }