aboutsummaryrefslogtreecommitdiffstats
path: root/roms/openbios/drivers/fw_cfg.c
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/openbios/drivers/fw_cfg.c
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/openbios/drivers/fw_cfg.c')
-rw-r--r--roms/openbios/drivers/fw_cfg.c153
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
+}