aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2024-01-03 00:08:29 +0100
committerHelge Deller <deller@gmx.de>2024-01-04 18:48:58 +0100
commit292ee73331f6f1e55122691a1b9bd59399a5c199 (patch)
tree021de4844bf2521861f461450beaa291a3a54ad4
parenta7efc718498cdbc1d547938bfbb308e177c45a8e (diff)
downloadseabios-hppa-292ee73331f6f1e55122691a1b9bd59399a5c199.zip
seabios-hppa-292ee73331f6f1e55122691a1b9bd59399a5c199.tar.gz
seabios-hppa-292ee73331f6f1e55122691a1b9bd59399a5c199.tar.bz2
parisc: Fix 64-bit firmware build
Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r--src/boot.c2
-rw-r--r--src/parisc/head.S71
-rw-r--r--src/parisc/hppa.h4
-rw-r--r--src/parisc/pafirmware.lds.S9
-rw-r--r--src/parisc/parisc.c71
-rw-r--r--src/types.h4
-rw-r--r--vgasrc/vgainit.c2
7 files changed, 116 insertions, 47 deletions
diff --git a/src/boot.c b/src/boot.c
index cf1b2fe..6f79648 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -932,7 +932,7 @@ bcv_prepboot(void)
static void
call_boot_entry(struct segoff_s bootsegip, u8 bootdrv)
{
- dprintf(1, "Booting from %04x:%04x\n", bootsegip.seg, bootsegip.offset);
+ dprintf(1, "Booting from %04x:%04lx\n", bootsegip.seg, bootsegip.offset);
struct bregs br;
memset(&br, 0, sizeof(br));
br.flags = F_IF;
diff --git a/src/parisc/head.S b/src/parisc/head.S
index da89558..c9b96b7 100644
--- a/src/parisc/head.S
+++ b/src/parisc/head.S
@@ -14,8 +14,17 @@
.macro load32 value, reg
ldil L%\value, \reg
ldo R%\value(\reg), \reg
+#ifdef CONFIG_64BIT
+ depdi 0, 31, 32, \reg
+#endif
.endm
+;! set the W bit
+#define set_PSW_W .level 2.0 ! ssm PSW_W_SM, %r0 ! .level LEVEL
+
+;! nuke the W bit
+#define clear_PSW_W .level 2.0 ! rsm PSW_W_SM, %r0 ! .level LEVEL
+
#define ENTRY(name) \
.export name !\
.align 4 !\
@@ -31,11 +40,16 @@ name:
#define BOOTADDR(x) (x)
.macro loadgp
+#ifdef CONFIG_64BIT
+ copy %r0, %r27
+#else
ldil L%$global$, %r27
ldo R%$global$(%r27), %r27
+#endif
.endm
#ifdef CONFIG_64BIT
+#define LEVEL 2.0w
#define LDREG ldd
#define STREG std
#define LDREGX ldd,s
@@ -51,6 +65,7 @@ name:
#define WORD_LEN 8
#define INT_LEN 4
#else /* CONFIG_64BIT */
+#define LEVEL 1.1
#define LDREG ldw
#define STREG stw
#define LDREGX ldwx,s
@@ -78,7 +93,7 @@ name:
.import $global$
.section ".head.text","ax"
- .level 1.1
+ .level LEVEL
/* On HPMC, the CPUs will start here at 0xf0000000 */
hpmc_entry:
@@ -103,6 +118,20 @@ ENTRY(startup)
rsm PSW_I, %r0 /* disable local irqs */
ssm PSW_Q, %r0 /* enable PSW_Q flag */
+#ifdef CONFIG_64BIT
+ /* check if we really run on 64-bit CPU */
+ ldo -1(%r0), %r1
+ mtctl %r1,%cr11
+ mfctl,w %cr11, %r1
+ ldo -31(%r1),%r1
+ cmpib,<>,n 0,%r1,1f
+ .word 0xfffdead0 /* immediately halt the emulator */
+1:
+ // set_PSW_W
+#else
+ clear_PSW_W
+#endif
+
/* Make sure space registers are set to zero */
mtsp %r0,%sr0
mtsp %r0,%sr1
@@ -113,11 +142,6 @@ ENTRY(startup)
mtsp %r0,%sr6
mtsp %r0,%sr7
- ;! nuke the W bit
- .level 2.0
- rsm PSW_W_SM, %r0
- .level 1.1
-
/* If CPU HPA is already set in CPU_HPA_CR_REG then the
* CPU is already initialized and the machine was only reset */
mfctl CPU_HPA_CR_REG, %r1
@@ -190,14 +214,14 @@ $smp_exit_loop:
$is_monarch_cpu:
/* Save boot_args in PAGE0->pad608[]. Only monarch CPU does this once. */
load32 BOOTADDR(0x608),%r1
- stw,ma %r26,4(%r1)
- stw,ma %r25,4(%r1)
- stw,ma %r24,4(%r1)
- stw,ma %r23,4(%r1)
- stw,ma %r22,4(%r1)
- stw,ma %r21,4(%r1)
- stw,ma %r20,4(%r1)
- stw,ma %r19,4(%r1)
+ STREGM %r26,WORD_LEN(%r1)
+ STREGM %r25,WORD_LEN(%r1)
+ STREGM %r24,WORD_LEN(%r1)
+ STREGM %r23,WORD_LEN(%r1)
+ STREGM %r22,WORD_LEN(%r1)
+ STREGM %r21,WORD_LEN(%r1)
+ STREGM %r20,WORD_LEN(%r1)
+ STREGM %r19,WORD_LEN(%r1)
$is_monarch_cpu_reboot:
/* Initialize stack pointer */
@@ -215,7 +239,7 @@ $is_monarch_cpu_reboot:
load32 BOOTADDR(_ebss),%r4
$bss_loop:
cmpb,<<,n %r3,%r4,$bss_loop
- stw,ma %r0,4(%r3)
+ STREGM %r0,WORD_LEN(%r3)
load32 BOOTADDR(start_parisc_firmware),%r3
bv 0(%r3)
@@ -268,7 +292,8 @@ ENTRY(toc_asm_entry)
/* save all general registers */
.set loop,0
.rept 32
- STREGM loop, WORD_LEN(PIM_PTR)
+ copy loop,TEMP
+ STREGM TEMP, WORD_LEN(PIM_PTR)
.set loop,loop+1
.endr
@@ -376,16 +401,13 @@ ENTRY(pdc_entry)
bv %r0(%rp) /* return with setting PSW_W */
.level 2.0
nop // ssm PSW_W_SM,%r0
- .level 1.1
+ .level LEVEL
END(pdc_entry)
/* pdc_entry_table will be copied into low memory. */
ENTRY(pdc_entry_table)
load32 pdc_entry,%r1
- ;! nuke the W bit
- .level 2.0
- rsm PSW_W_SM, %r31
- .level 1.1
+ clear_PSW_W
bv,n %r0(%r1)
END(pdc_entry_table)
@@ -408,10 +430,7 @@ ENTRY(iodc_entry)
stw %arg1,-40(%sp)
stw %arg2,-44(%sp)
stw %arg3,-48(%sp)
- ;! nuke the W bit
- .level 2.0
- rsm PSW_W_SM, %r31
- .level 1.1
+ clear_PSW_W
stw %r31,PSW_OFFSET2(%r0) /* store PSW_W */
ldo -FRAME_SIZE(%sp),%arg0
@@ -433,7 +452,7 @@ ENTRY(iodc_entry)
bv %r0(%rp) /* return with setting PSW_W */
.level 2.0
nop // ssm PSW_W_SM,%r0
- .level 1.1
+ .level LEVEL
END(iodc_entry)
/****************************************************************
diff --git a/src/parisc/hppa.h b/src/parisc/hppa.h
index 9c82b70..3b7e7bb 100644
--- a/src/parisc/hppa.h
+++ b/src/parisc/hppa.h
@@ -6,6 +6,10 @@
#define SEABIOS_HPPA_VERSION 13
#define SEABIOS_HPPA_VERSION_STR "13"
+#ifdef __LP64__
+#define CONFIG_64BIT
+#endif
+
#include "parisc/hppa_hardware.h"
#ifndef __ASSEMBLY__
diff --git a/src/parisc/pafirmware.lds.S b/src/parisc/pafirmware.lds.S
index 9975596..4af3865 100644
--- a/src/parisc/pafirmware.lds.S
+++ b/src/parisc/pafirmware.lds.S
@@ -1,11 +1,20 @@
#include "parisc/hppa_hardware.h"
+#if BITS == 64
+OUTPUT_FORMAT("elf64-hppa-linux")
+OUTPUT_ARCH(hppa:hppa2.0w)
+#else
OUTPUT_FORMAT("elf32-hppa-linux")
OUTPUT_ARCH(hppa)
+#endif
ENTRY(startup)
SECTIONS
{
+#if BITS == 64
+ . = 0xfffffff000000000 + FIRMWARE_START;
+#else
. = FIRMWARE_START;
+#endif
/* align on next page boundary */
. = ALIGN(4096);
diff --git a/src/parisc/parisc.c b/src/parisc/parisc.c
index c90902d..df85f1c 100644
--- a/src/parisc/parisc.c
+++ b/src/parisc/parisc.c
@@ -52,7 +52,13 @@ union {
struct pdc_toc_pim_20 pim20;
} pim_toc_data[HPPA_MAX_CPUS] __VISIBLE __aligned(8);
-#define is_64bit() 0 /* we only support 32-bit PDC for now. */
+#if defined(__LP64__)
+# define is_64bit() 1 /* 64-bit PDC */
+# define cpu_bit_width 64
+#else
+# define is_64bit() 0 /* 32-bit PDC */
+char cpu_bit_width;
+#endif
u8 BiosChecksum;
@@ -98,7 +104,7 @@ void wrmsr_smp(u32 index, u64 val) { }
********************************************************/
/* boot_args[] variables provided by qemu */
-#define boot_args PAGE0->pad608
+#define boot_args ((unsigned long *)(uintptr_t)&PAGE0->pad608)
#define ram_size boot_args[0]
#define linux_kernel_entry boot_args[1]
#define cmdline boot_args[2]
@@ -124,7 +130,6 @@ int sti_font;
char qemu_version[16] = "unknown version";
char qemu_machine[16] = "B160L";
-char cpu_bit_width;
char has_astro;
#define PCI_HPA DINO_HPA /* initial temp. PCI bus */
unsigned long pci_hpa = PCI_HPA; /* HPA of Dino or Elroy0 */
@@ -254,7 +259,7 @@ void flush_data_cache(char *start, size_t length)
void memdump(void *mem, unsigned long len)
{
- printf("memdump @ 0x%x : ", (unsigned int) mem);
+ printf("memdump @ 0x%lx : ", (unsigned long) mem);
while (len--) {
printf("0x%x ", (unsigned int) *(unsigned char *)mem);
mem++;
@@ -1867,8 +1872,8 @@ static int pdc_mem(unsigned int *arg)
unsigned long option = ARG1;
unsigned long *result = (unsigned long *)ARG2;
- // only implemented on 64bit PDC!
- if (sizeof(unsigned long) == sizeof(unsigned int))
+ // only implemented on 64bit PDC variants
+ if (!is_64bit())
return PDC_BAD_PROC;
switch (option) {
@@ -1885,6 +1890,10 @@ static int pdc_mem(unsigned int *arg)
case PDC_MEM_GOODMEM:
GoldenMemory = ARG3;
return PDC_OK;
+ case PDC_MEM_GET_MEMORY_SYSTEM_TABLES_SIZE:
+ case PDC_MEM_GET_MEMORY_SYSTEM_TABLES:
+ /* not yet implemented for 64-bit */
+ return PDC_BAD_PROC;
}
dprintf(0, "\n\nSeaBIOS: Check PDC_MEM option %ld ARG3=%x ARG4=%x ARG5=%x\n", option, ARG3, ARG4, ARG5);
return PDC_BAD_PROC;
@@ -2254,6 +2263,18 @@ static int pdc_pat_pd(unsigned int *arg)
return PDC_BAD_OPTION;
}
+static int pdc_pat_mem(unsigned int *arg)
+{
+ unsigned long option = ARG1;
+
+ switch (option) {
+ default:
+ break;
+ }
+ dprintf(0, "\n\nSeaBIOS: Unimplemented PDC_PAT_MEM function %ld ARG3=%x ARG4=%x ARG5=%x\n", option, ARG3, ARG4, ARG5);
+ return PDC_BAD_OPTION;
+}
+
int __VISIBLE parisc_pdc_entry(unsigned int *arg FUNC_MANY_ARGS)
{
@@ -2394,6 +2415,11 @@ int __VISIBLE parisc_pdc_entry(unsigned int *arg FUNC_MANY_ARGS)
if (firmware_width_locked)
return PDC_BAD_PROC;
return pdc_pat_pd(arg);
+
+ case PDC_PAT_MEM:
+ if (firmware_width_locked)
+ return PDC_BAD_PROC;
+ return pdc_pat_mem(arg);
}
printf("\n** WARNING **: SeaBIOS: Unimplemented PDC proc %s(%d) option %d result=%x ARG3=%x ",
@@ -2751,37 +2777,44 @@ static int parisc_boot_menu(unsigned long *iplstart, unsigned long *iplend,
* FIRMWARE MAIN ENTRY POINT
********************************************************/
-static const struct pz_device mem_cons_sti_boot = {
+static struct pz_device mem_cons_sti_boot = {
.hpa = LASI_GFX_HPA,
- .iodc_io = (unsigned long)&iodc_entry,
.cl_class = CL_DISPL,
};
static struct pz_device mem_kbd_sti_boot = {
.hpa = LASI_PS2KBD_HPA,
- .iodc_io = (unsigned long)&iodc_entry,
.cl_class = CL_KEYBD,
};
static struct pz_device mem_cons_boot = {
.hpa = PARISC_SERIAL_CONSOLE - 0x800,
- .iodc_io = (unsigned long)&iodc_entry,
.cl_class = CL_DUPLEX,
};
static struct pz_device mem_kbd_boot = {
.hpa = PARISC_SERIAL_CONSOLE - 0x800,
- .iodc_io = (unsigned long)&iodc_entry,
.cl_class = CL_KEYBD,
};
static struct pz_device mem_boot_boot = {
.dp.path.flags = PF_AUTOBOOT,
.hpa = DINO_SCSI_HPA, // will be overwritten
- .iodc_io = (unsigned long) &iodc_entry,
.cl_class = CL_RANDOM,
};
+static void initialize_iodc_entry(void)
+{
+ unsigned long iodc_p = (unsigned long) &iodc_entry;
+
+ /* need to initialize at runtime, required on 64-bit firmware */
+ mem_cons_sti_boot.iodc_io = iodc_p;
+ mem_kbd_sti_boot.iodc_io = iodc_p;
+ mem_cons_boot.iodc_io = iodc_p;
+ mem_kbd_boot.iodc_io = iodc_p;
+ mem_boot_boot.iodc_io = iodc_p;
+}
+
#if 0
static void find_pci_slot_for_dev(unsigned int vendor, char *pci_slot)
{
@@ -2912,6 +2945,9 @@ void __VISIBLE start_parisc_firmware(void)
char bootdrive = (char)cmdline; // c = hdd, d = CD/DVD
show_boot_menu = (linux_kernel_entry == 1);
+ initialize_iodc_entry();
+
+#ifndef __LP64__
// detect if we emulate a 32- or 64-bit CPU.
// set all bits in cr11, read back, and if the return
// value is 63 this is a 64-bit capable CPU.
@@ -2920,13 +2956,14 @@ void __VISIBLE start_parisc_firmware(void)
/* this is: mfctl,w sar,r1: */
asm(".word 0x016048a0 + 1 ! copy %%r1,%0\n" : "=r" (i): : "r1");
cpu_bit_width = (i == 63) ? 64 : 32;
+#endif
/* lock all 64-bit and PAT functions until unlocked from OS
* via PDC_MODEL/PDC_MODEL_CAPABILITIES call */
firmware_width_locked = 1;
psw_defaults = PDC_PSW_ENDIAN_BIT;
- if (0 && cpu_bit_width == 64) {
+ if (is_64bit() && cpu_bit_width == 64) {
/* enable 64-bit PSW by default */
psw_defaults |= PDC_PSW_WIDE_BIT;
current_machine->pdc_model.width = 1;
@@ -3074,7 +3111,7 @@ void __VISIBLE start_parisc_firmware(void)
if (artist_present()) {
sti_rom_init();
sti_console_init(&sti_proc_rom);
- PAGE0->proc_sti = (u32)&sti_proc_rom;
+ PAGE0->proc_sti = (uintptr_t)&sti_proc_rom;
if (has_astro)
kbd_init();
else
@@ -3107,13 +3144,13 @@ void __VISIBLE start_parisc_firmware(void)
chassis_code = 0;
cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */
- dprintf(1, "\nPARISC SeaBIOS Firmware, %d x %d-bit PA-RISC CPU at %d.%06d MHz, %d MB RAM.\n",
+ dprintf(1, "\nPARISC SeaBIOS Firmware, %ld x %d-bit PA-RISC CPU at %d.%06d MHz, %ld MB RAM.\n",
smp_cpus, cpu_bit_width, cpu_hz / 1000000, cpu_hz % 1000000,
ram_size/1024/1024);
if (ram_size < MIN_RAM_SIZE) {
printf("\nSeaBIOS: Machine configured with too little "
- "memory (%d MB), minimum is %d MB.\n\n",
+ "memory (%ld MB), minimum is %d MB.\n\n",
ram_size/1024/1024, MIN_RAM_SIZE/1024/1024);
hlt();
}
@@ -3176,7 +3213,7 @@ void __VISIBLE start_parisc_firmware(void)
i < 10 ? " ":"", i, i?"Idle ":"Active");
printf("\n\n");
printf(" Emulated machine: HP %s (%d-bit %s)\n"
- " Available memory: %u MB\n"
+ " Available memory: %lu MB\n"
" Good memory required: %d MB\n\n",
qemu_machine, cpu_bit_width, (cpu_bit_width == 64) ? "PA2.0" : "PA1.1",
ram_size/1024/1024, MIN_RAM_SIZE/1024/1024);
diff --git a/src/types.h b/src/types.h
index 5887ecf..cadefcb 100644
--- a/src/types.h
+++ b/src/types.h
@@ -24,7 +24,7 @@ union u64_u32_u {
#if MODE16 == 1
typedef u16 portaddr_t;
#else
-typedef unsigned int portaddr_t;
+typedef unsigned long portaddr_t;
#endif
// Definition for common 16bit segment/offset pointers.
@@ -120,7 +120,7 @@ extern void __force_link_error__only_in_16bit(void) __noreturn;
# define ASSERT32FLAT() do { } while (0)
#endif
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
diff --git a/vgasrc/vgainit.c b/vgasrc/vgainit.c
index 56222b4..4b6ed74 100644
--- a/vgasrc/vgainit.c
+++ b/vgasrc/vgainit.c
@@ -54,7 +54,7 @@ allocate_pmm(u32 size, int highmem, int aligned)
if (checksum_far(SEG_BIOS, pmm, GET_FARVAR(SEG_BIOS, pmm->length)))
continue;
struct segoff_s entry = GET_FARVAR(SEG_BIOS, pmm->entry);
- dprintf(1, "Attempting to allocate %u bytes %s via pmm call to %04x:%04x\n"
+ dprintf(1, "Attempting to allocate %u bytes %s via pmm call to %04x:%04lx\n"
, size, highmem ? "highmem" : "lowmem"
, entry.seg, entry.offset);
u16 res1, res2;