diff options
author | Helge Deller <deller@gmx.de> | 2023-10-29 22:53:16 +0100 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2023-10-31 08:26:22 +0100 |
commit | c1da8d0ea21e2c8be526284233bec9841a79aa10 (patch) | |
tree | 0ba54e38ccda95cdc08e3915685c73b983965f1a | |
parent | 08402d3d1b5af9a13b056d609836f06a0697a70c (diff) | |
download | seabios-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.c | 45 |
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); } |