diff options
author | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
---|---|---|
committer | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/openbios/drivers/fw_cfg.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/openbios/drivers/fw_cfg.c')
-rw-r--r-- | roms/openbios/drivers/fw_cfg.c | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/roms/openbios/drivers/fw_cfg.c b/roms/openbios/drivers/fw_cfg.c new file mode 100644 index 000000000..1cd3ec2b1 --- /dev/null +++ b/roms/openbios/drivers/fw_cfg.c @@ -0,0 +1,153 @@ +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/byteorder.h" +#include "libopenbios/ofmem.h" +#define NO_QEMU_PROTOS +#include "arch/common/fw_cfg.h" + +#if !defined(CONFIG_SPARC64) +static volatile uint16_t *fw_cfg_cmd; +static volatile uint8_t *fw_cfg_data; + +static void +fw_cfg_read_bytes(char *buf, unsigned int nbytes) +{ + unsigned int i; + + for (i = 0; i < nbytes; i++) + buf[i] = *fw_cfg_data; +} + +void +fw_cfg_read(uint16_t cmd, char *buf, unsigned int nbytes) +{ + *fw_cfg_cmd = cmd; + fw_cfg_read_bytes(buf, nbytes); +} +#else +// XXX depends on PCI bus location, should be removed +static void +fw_cfg_read_bytes(char *buf, unsigned int nbytes) +{ + unsigned int i; + + for (i = 0; i < nbytes; i++) + buf[i] = inb(CONFIG_FW_CFG_ADDR + 1); +} + +void +fw_cfg_read(uint16_t cmd, char *buf, unsigned int nbytes) +{ + outw(cmd, CONFIG_FW_CFG_ADDR); + fw_cfg_read_bytes(buf, nbytes); +} +#endif + +uint64_t +fw_cfg_read_i64(uint16_t cmd) +{ + uint64_t buf; + + fw_cfg_read(cmd, (char *)&buf, sizeof(uint64_t)); + + return __le64_to_cpu(buf); +} + +uint32_t +fw_cfg_read_i32(uint16_t cmd) +{ + uint32_t buf; + + fw_cfg_read(cmd, (char *)&buf, sizeof(uint32_t)); + + return __le32_to_cpu(buf); +} + +uint16_t +fw_cfg_read_i16(uint16_t cmd) +{ + uint16_t buf; + + fw_cfg_read(cmd, (char *)&buf, sizeof(uint16_t)); + + return __le16_to_cpu(buf); +} + +uint32_t +fw_cfg_find_file(const char *filename, uint16_t *select, uint32_t *size) +{ + FWCfgFile f; + unsigned int i; + uint32_t buf, count; + + /* Unusually all FW_CFG_FILE_DIR fields are BE */ + fw_cfg_read(FW_CFG_FILE_DIR, (char *)&buf, sizeof(uint32_t)); + count = __be32_to_cpu(buf); + + for (i = 0; i < count; i++) { + fw_cfg_read_bytes((char *)&f, sizeof(f)); + + if (!strcmp(f.name, filename)) { + *select = __be16_to_cpu(f.select); + *size = __be32_to_cpu(f.size); + + return -1; + } + } + + return 0; +} + +char * +fw_cfg_read_file(const char *filename, uint32_t *size) +{ + uint16_t cmd; + uint32_t nbytes; + char *buf; + + if (fw_cfg_find_file(filename, &cmd, &nbytes)) { + buf = malloc(nbytes); + fw_cfg_read(cmd, buf, nbytes); + *size = nbytes; + return buf; + } + + return NULL; +} + +// +// ( fname fnamelen -- buf buflen -1 | 0 ) +// + +void +forth_fw_cfg_read_file(void) +{ + char *filename = pop_fstr_copy(); + char *buffer; + uint32_t size; + + buffer = fw_cfg_read_file(filename, &size); + if (buffer) { + PUSH(pointer2cell(buffer)); + PUSH(size); + PUSH(-1); + + return; + } + + PUSH(0); +} + +void +fw_cfg_init(void) +{ +#if defined(CONFIG_SPARC32) + fw_cfg_cmd = (void *)ofmem_map_io(CONFIG_FW_CFG_ADDR, 2); + fw_cfg_data = (uint8_t *)fw_cfg_cmd + 2; +#elif defined(CONFIG_SPARC64) + // Nothing for the port version +#elif defined(CONFIG_PPC) + fw_cfg_cmd = (void *)CONFIG_FW_CFG_ADDR; + fw_cfg_data = (void *)(CONFIG_FW_CFG_ADDR + 2); +#endif +} |