aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2023-10-29 22:53:16 +0100
committerHelge Deller <deller@gmx.de>2023-10-31 08:26:22 +0100
commitc1da8d0ea21e2c8be526284233bec9841a79aa10 (patch)
tree0ba54e38ccda95cdc08e3915685c73b983965f1a
parent08402d3d1b5af9a13b056d609836f06a0697a70c (diff)
downloadseabios-hppa-c1da8d0ea21e2c8be526284233bec9841a79aa10.zip
seabios-hppa-c1da8d0ea21e2c8be526284233bec9841a79aa10.tar.gz
seabios-hppa-c1da8d0ea21e2c8be526284233bec9841a79aa10.tar.bz2
parisc/sti: Fix STI crash with fonts with 64-bit Linux kernel
Just swapping font "next-font" pointers 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 the STI ROM before the OS starts. A Linux kernel patch to avoid the crash was added in kernel 6.7. Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r--src/parisc/stirom.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/parisc/stirom.c b/src/parisc/stirom.c
index ddc6285..a694959 100644
--- a/src/parisc/stirom.c
+++ b/src/parisc/stirom.c
@@ -1,6 +1,8 @@
#include "sticore.h"
#include "pdc.h"
#include "hppa.h"
+#include "../malloc.h"
+#include "../string.h"
#define ARTIST_VRAM_IDX 0x4a0
#define ARTIST_VRAM_BITMASK 0x5a0
@@ -3597,15 +3599,58 @@ void sti_rom_init(void)
/* 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);
}