aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2024-04-02 14:55:53 +0200
committerHelge Deller <deller@gmx.de>2024-04-02 14:55:53 +0200
commit83de49c6fff0d04a10d3d2b7626996c1ecf7d54f (patch)
treeb8542f7d7ad252cc4d23140b367be4175fe99b93
parent3d8f72acd1a80538ac7c21f71b6a6e4779ff2d7f (diff)
downloadseabios-hppa-83de49c6fff0d04a10d3d2b7626996c1ecf7d54f.zip
seabios-hppa-83de49c6fff0d04a10d3d2b7626996c1ecf7d54f.tar.gz
seabios-hppa-83de49c6fff0d04a10d3d2b7626996c1ecf7d54f.tar.bz2
parisc: Build artist / Visualize EG PCI ROM
Build a ROM for Visualize EG PCI. Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r--Makefile5
-rw-r--r--Makefile.parisc19
-rw-r--r--src/parisc/make-sti-rom.c224
3 files changed, 245 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 3a7e119..a02b50a 100644
--- a/Makefile
+++ b/Makefile
@@ -112,8 +112,9 @@ endif
# Install parisc firmware into qemu pc-bios directory
parisc-qemu-install: parisc
- hppa-linux-gnu-objcopy -S out/hppa-firmware.img ../../pc-bios/hppa-firmware.img
- hppa64-linux-gnu-objcopy -S out-64/hppa-firmware64.img ../../pc-bios/hppa-firmware64.img
+ cp out/artist-pci.rom ../../pc-bios/
+ hppa-linux-gnu-objcopy -S out/hppa-firmware.img ../../pc-bios/
+ hppa64-linux-gnu-objcopy -S out-64/hppa-firmware64.img ../../pc-bios/
# Make definitions
.PHONY : all clean distclean parisc FORCE
diff --git a/Makefile.parisc b/Makefile.parisc
index 5c34eb3..cf90258 100644
--- a/Makefile.parisc
+++ b/Makefile.parisc
@@ -103,6 +103,7 @@ endif
target-y :=
target-$(CONFIG_PARISC) += $(OUT)hppa-firmware$(BIT_SUFFIX).img
+target-$(CONFIG_PARISC) += $(OUT)artist-pci.rom
all: $(target-y)
@@ -169,7 +170,23 @@ $(OUT)hppa-firmware$(BIT_SUFFIX).img: $(OUT)autoconf.h $(OUT)head.o $(OUT)ccode3
@echo " Linking $@"
$(Q)$(CPP) $(CPPFLAGS) -Isrc -D__ASSEMBLY__ -DBITS=$(BITS) src/parisc/pafirmware.lds.S -o $(OUT)pafirmware.lds
$(Q)$(CC) $(CFLAGS32FLAT) -c src/version.c -o $(OUT)version.o
- $(Q)$(LD) -N -T $(OUT)pafirmware.lds $(OUT)head.o $(OUT)version.o -X -o $@ -e startup --as-needed $(OUT)ccode32flat.o $(LIBGCC)
+ $(Q)$(LD) -N -T $(OUT)pafirmware.lds $(OUT)head.o $(OUT)version.o -X -o $@ \
+ -e startup --as-needed $(OUT)ccode32flat.o $(LIBGCC)
+
+$(OUT)sti-rom.bin: $(OUT)hppa-firmware$(BIT_SUFFIX).img
+ @echo " Building $@"
+ $(Q)$(OBJCOPY) -j .sti $< $(OUT)sti-rom.elf
+ $(Q)$(OBJDUMP) -t $(OUT)sti-rom.elf | grep " sti_" | sort | \
+ awk -F ' ' '{print "#define off$(BIT_SUFFIX)_" $$6 "\t0x" $$1}' > $(OUT)sti-rom-offsets.h
+ $(Q)$(OBJCOPY) $(OUT)sti-rom.elf --output-target binary $@
+
+$(OUT)sti-rom-offsets.h: $(OUT)sti-rom.bin
+
+$(OUT)make-sti-rom$(BIT_SUFFIX): src/parisc/make-sti-rom.c $(OUT)sti-rom-offsets.h
+ $(HOSTCC) -I. $< -o $@
+
+$(OUT)artist-pci.rom: $(OUT)make-sti-rom$(BIT_SUFFIX) $(OUT)sti-rom.bin $(OUT)sti-rom-offsets.h
+ $(OUT)make-sti-rom$(BIT_SUFFIX) $(OUT)sti-rom.bin $@
################ Kconfig rules
diff --git a/src/parisc/make-sti-rom.c b/src/parisc/make-sti-rom.c
new file mode 100644
index 0000000..07f6a3e
--- /dev/null
+++ b/src/parisc/make-sti-rom.c
@@ -0,0 +1,224 @@
+/*
+ * Build STI ROM for qemu
+ *
+ * (C) 2024 Helge Deller <deller@gmx.de>
+ *
+ * See:
+ * https://parisc.wiki.kernel.org/images-parisc/e/e3/Sti.pdf
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <assert.h>
+#include <string.h>
+
+#include "out/sti-rom-offsets.h"
+#include "src/hw/pci_ids.h"
+
+#define BUILD_STI_ROM
+#include "src/parisc/sticore.h"
+
+#define ROMSIZE 64 * 1024
+#define BLOCKSIZE 512
+#define STI_ROM_OFFSET sizeof(struct pci_rom_header) /* STI ROM starts after PCI ROM HEADER */
+
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+
+struct pci_data_structure {
+ char sig[4];
+ uint16_t ven, dev, res1, ds_len;
+ uint32_t class_and_rev;
+ uint16_t len, rev;
+ char code, indicator, res2, res3;
+};
+
+struct pci_rom_header {
+ uint32_t sig;
+ uint32_t rom_type;
+ uint32_t sti_image_offset;
+ uint16_t rom_size; /* multiple of 512 */
+ uint16_t sti_region_mapper_offset;
+ uint32_t empty[2];
+ uint16_t pci_ds_offset;
+ struct pci_data_structure ds;
+ char pci_region_mapper[16];
+};
+
+char *rom;
+struct pci_rom_header *rh;
+char *sti_rom_start;
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ #define host_to_be16(x) __builtin_bswap16(x)
+ #define host_to_be32(x) __builtin_bswap32(x)
+ #define host_to_le16(x) (x)
+ #define host_to_le32(x) (x)
+#else
+ #define host_to_be16(x) (x)
+ #define host_to_be32(x) (x)
+ #define host_to_le16(x) __builtin_bswap16(x)
+ #define host_to_le32(x) __builtin_bswap32(x)
+#endif
+
+int main(int argc, char *argv[])
+{
+ int fh;
+ ssize_t size;
+ unsigned long addr;
+
+ rom = malloc(ROMSIZE);
+ assert(rom);
+ memset(rom, 0, ROMSIZE);
+
+ fh = open(argv[1], O_RDONLY);
+ assert(fh >= 0);
+ sti_rom_start = &rom[STI_ROM_OFFSET];
+ size = read(fh, sti_rom_start, 2 * ROMSIZE);
+ assert(size < ROMSIZE);
+ close(fh);
+
+ rh = (void *)rom;
+ rh->sig = host_to_le32(0xaa55);
+ rh->rom_type = host_to_le32(1 << 24);
+ rh->sti_image_offset = host_to_le32(STI_ROM_OFFSET);
+ rh->rom_size = host_to_le16(ROMSIZE / BLOCKSIZE);
+ rh->sti_region_mapper_offset = host_to_le16(
+ offsetof(struct pci_rom_header, pci_region_mapper));
+ rh->pci_region_mapper[0] = 0x10; /* PCI_BASE_ADDRESS_0 */
+ rh->pci_region_mapper[1] = 0x10; /* PCI_BASE_ADDRESS_0 */
+ rh->pci_region_mapper[2] = 0x10; /* PCI_BASE_ADDRESS_0 */
+ rh->pci_region_mapper[3] = 0x10; /* PCI_BASE_ADDRESS_0 */
+ rh->pci_ds_offset = host_to_le16(offsetof(struct pci_rom_header, ds));
+
+ rh->ds.sig[0] = 'P';
+ rh->ds.sig[1] = 'C';
+ rh->ds.sig[2] = 'I';
+ rh->ds.sig[3] = 'R';
+ rh->ds.ven = host_to_le16(PCI_VENDOR_ID_HP);
+ rh->ds.dev = host_to_le16(PCI_DEVICE_ID_HP_VISUALIZE_EG);
+ rh->ds.ds_len = host_to_le16(sizeof(rh->ds));
+ rh->ds.class_and_rev = host_to_le32(PCI_CLASS_DISPLAY_OTHER << 16);
+ rh->ds.len = host_to_le16(ROMSIZE / BLOCKSIZE);
+ rh->ds.rev = host_to_le16(0);
+ rh->ds.code = 0x10; /* Note: NOT 2, as documented in PCI spec! */
+ rh->ds.indicator = 1<<7; /* last image */
+
+
+#define STI_OFFSET(_x) ((off_ ## _x) - off_sti_proc_rom)
+
+ struct sti_rom *sti_proc_rom;
+ unsigned int sti_rom_size;
+
+ sti_proc_rom = (void *)sti_rom_start;
+
+#if 0
+ region_t *sti_region_list = sti_rom_start + STI_OFFSET(sti_region_list);
+
+ // sti_rom_size = (_sti_rom_end - _sti_rom_start) / 4096;
+ sti_rom_size = STI_OFFSET(sti_end) / 4096;
+ if (sti_region_list[0].region_desc.length != sti_rom_size) {
+ /* The STI ROM size is wrong. Fix it. */
+ region_t *rp = (region_t *) &sti_region_list[0];
+ rp->region_desc.length = sti_rom_size;
+ }
+#endif
+
+#if 0
+ extern int sti_font; /* in parisc.c, from opt/font fw_cfg option */
+ struct font *font_ptr, *font_next, *font_start;
+ int i;
+
+ /* Swap selected font as first, then chain all. */
+ if (sti_font <= 0 || sti_font > ARRAY_SIZE(fontlist))
+ sti_font = 1;
+
+ /* Swap selected font in as first font */
+ font_next = fontlist[0];
+ fontlist[0] = fontlist[sti_font - 1];
+ fontlist[sti_font - 1] = font_next;
+
+#define ENABLE_FONTCOPY
+#ifdef ENABLE_FONTCOPY
+ {
+ struct font *fontlist_temp[ARRAY_SIZE(fontlist)];
+ unsigned long font_size, font_addr;
+ /* * The trivial swapping above breaks the sti driver on older 64-bit Linux
+ * kernels which take the "next_font" pointer as unsigned int (instead of
+ * signed int) and thus calculates a wrong font start address. Avoid the crash
+ * by sorting the fonts in memory. Maybe HP-UX has problems with that too?
+ * A Linux kernel patch to avoid that was added in kernel 6.7.
+ */
+ #define FONT_SIZE(f) (sizeof(f->hdr) + f->hdr.bytes_per_char * (unsigned int)(f->hdr.last_char - f->hdr.first_char + 1))
+ font_start = fontlist[0]; /* the lowest font ptr */
+ for (i = 0; i < ARRAY_SIZE(fontlist); i++) {
+ font_ptr = fontlist[i];
+ if (font_ptr < font_start) /* is font ptr lower? */
+ font_start = font_ptr;
+ font_size = FONT_SIZE(font_ptr);
+ font_next = malloc_tmplow(font_size);
+ memcpy(font_next, font_ptr, font_size);
+ fontlist_temp[i] = font_next;
+ }
+ /* font_start is now starting address */
+ font_addr = (unsigned long) font_start;
+ for (i = 0; i < ARRAY_SIZE(fontlist); i++) {
+ font_ptr = fontlist_temp[i];
+ font_size = FONT_SIZE(font_ptr);
+ memcpy((void *)font_addr, font_ptr, font_size);
+ malloc_pfree((unsigned long) font_ptr);
+ fontlist[i] = (struct font *) font_addr;
+ font_addr += font_size;
+ font_addr = ALIGN(font_addr, 32);
+ }
+ }
+#endif
+
+ /* Now chain all fonts */
+ font_start = fontlist[0];
+ sti_proc_rom.font_start = STI_OFFSET(*font_start);
+ for (i = 0; i < ARRAY_SIZE(fontlist)-1; i++) {
+ font_ptr = fontlist[i];
+ if (i == ARRAY_SIZE(fontlist)-1) {
+ /* last entry? */
+ font_ptr->hdr.next_font = 0;
+ continue;
+ }
+ font_next = fontlist[i+1];
+ font_ptr->hdr.next_font = STI_FONT_OFFSET(font_next, font_start);
+ }
+
+#endif
+
+
+ addr = STI_OFFSET(sti_end);
+ addr = (addr + 4096) & ~(4096-1); // align to page boundary
+ addr -= 1;
+ sti_proc_rom->last_addr = host_to_be32(addr);
+
+ sti_proc_rom->font_start = host_to_be32(STI_OFFSET(sti_rom_font_10x20));
+
+ sti_proc_rom->state_mgmt = host_to_be32(STI_OFFSET(sti_state_mgmt));
+ sti_proc_rom->inq_conf = host_to_be32(STI_OFFSET(sti_inq_conf));
+ sti_proc_rom->init_graph = host_to_be32(STI_OFFSET(sti_init_graph));
+ sti_proc_rom->block_move = host_to_be32(STI_OFFSET(sti_bmove));
+ sti_proc_rom->region_list = host_to_be32(STI_OFFSET(sti_region_list));
+ sti_proc_rom->font_unpmv = host_to_be32(STI_OFFSET(sti_font_unpmv));
+ sti_proc_rom->self_test = host_to_be32(STI_OFFSET(sti_self_test));
+ sti_proc_rom->mon_tbl_addr = host_to_be32(STI_OFFSET(sti_mon_table));
+ sti_proc_rom->user_data_addr = host_to_be32(STI_OFFSET(sti_user_data));
+ sti_proc_rom->excep_hdlr = host_to_be32(STI_OFFSET(sti_excep_hdlr));
+ sti_proc_rom->set_cm_entry = host_to_be32(STI_OFFSET(sti_set_cm_entry));
+ sti_proc_rom->dma_ctrl = host_to_be32(STI_OFFSET(sti_dma_ctrl));
+ sti_proc_rom->end = host_to_be32(STI_OFFSET(sti_end));
+// update_crc(&sti_proc_rom);
+
+
+ /* finally write ROM image */
+ fh = creat(argv[2], 0600);
+ assert(fh >= 0);
+ write(fh, rom, ROMSIZE);
+ close(fh);
+}
+