This patchset is loosely based on earlier work by BALATON Zoltan <balaton(a)eik.bme.hu>
and provides basic infrastructure to allow OpenBIOS to enable PCI device
bus mastering.
Following on from discussions on the QEMU mailing list, it seems that Apple's OF
enables bus mastering for some PCI devices by default, and as a result some buggy
drivers forget to explicitly enable it and hence these devices fail under QEMU's
emulation.
The first 3 patches add the basic support routines while the last 2 patches enable
bus mastering for the rtl8139 card on Apple PPC machines which is required for
OS X and MorphOS.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland(a)ilande.co.uk>
Mark Cave-Ayland (5):
pci: introduce ob_pci_enable_bus_master() function
pci: introduce ob_pci_is_bus_master_capable() function
pci: add PCI database entry for rtl8139 network card
pci: add rtl8139_config_cb() to configure rtl8139 network cards
ppc: mark PCI slots 0-2 for Apple PPC machies as bus master capable
openbios-devel/arch/ppc/qemu/init.c | 9 ++++---
openbios-devel/drivers/pci.c | 44 +++++++++++++++++++++++++++++++++
openbios-devel/drivers/pci_database.c | 6 +++++
openbios-devel/drivers/pci_database.h | 4 +++
openbios-devel/include/drivers/pci.h | 2 ++
5 files changed, 62 insertions(+), 3 deletions(-)
--
1.7.10.4
On Apr 17, 2016, at 11:05 AM, Mark Cave-Ayland wrote:
> On 17/04/16 15:50, Programmingkid wrote:
>
>> Good news, I found out why replacing '\r' with '\n' works to boot Mac OS 9. It is because there are several words that require that character to be at the end of the line.
>>
>> http://www.complang.tuwien.ac.at/forth/1275.ps
>> This is the specifications to Open Firmware. Just do a search for EOL (End of Line a.k.a '\n'). You will see that several words need it in order to work.
>>
>> They will look like this:
>>
>> dev ( "device-specifier<eol>" -- )
>>
>> The <eol> text is what specifies that '\n' should be at the end of the line.
>
> Really? Interesting. Can you provide a self-contained test case that
> demonstrates that it is in fact the line ending that causes this
> independent of the r-stack manipulation? Bear in mind that OpenBIOS may
> deviate from the specification in its behaviour here.
I implemented another stack that two new words use in place of >r and r> when running code in the bootscript. I see this message with and without the '\r' to '\n' patch:
>> Dictionary space overflow: dicthead=000c3fe4 dictlimit=00080000
this image is not for this platform
This means the implementing another stack did not fix the problem. It appears to make it worse.
Here is the patch:
Index: include/libc/string.h
===================================================================
--- include/libc/string.h (revision 1391)
+++ include/libc/string.h (working copy)
@@ -47,7 +47,7 @@
extern char *strdup( const char *str );
extern int strcasecmp( const char *cs, const char *ct );
extern int strncasecmp( const char *cs, const char *ct, size_t count );
-
+extern char *strstr(char *buffer, const char *search_string);
extern char *strncpy_nopad( char *dest, const char *src, size_t n );
#define _U 0x01 /* upper */
Index: kernel/bootstrap.c
===================================================================
--- kernel/bootstrap.c (revision 1391)
+++ kernel/bootstrap.c (working copy)
@@ -89,7 +89,7 @@
"here", "here!", "dobranch", "do?branch", "unaligned-w@",
"unaligned-w!", "unaligned-l@", "unaligned-l!", "ioc@", "iow@",
"iol@", "ioc!", "iow!", "iol!", "i", "j", "call", "sys-debug",
- "$include", "$encode-file", "(debug", "(debug-off)"
+ "$include", "$encode-file", "(debug", "(debug-off)", "sub_>r", "sub_r>"
};
/*
Index: kernel/forth.c
===================================================================
--- kernel/forth.c (revision 1391)
+++ kernel/forth.c (working copy)
@@ -1848,6 +1848,37 @@
PUSH(rstack[rstackcnt - 2]);
}
+/* The substitute return stack */
+#define MAX_SUB_RSTACK_SIZE 100
+static int sub_return_stack[MAX_SUB_RSTACK_SIZE];
+static int top = 0;
+
+/*
+ * sub_>r ( i -- ) (Substitute R: -- i )
+ */
+
+static void sub_gt_r(void)
+{
+ if (top >= MAX_SUB_RSTACK_SIZE) {
+ printf_console("Stack overflow\n");
+ return;
+ }
+ sub_return_stack[top++] = POP();
+}
+
+/*
+ * sub_r> ( -- i ) (Substitute R: i -- )
+ */
+
+static void sub_r_gt(void)
+{
+ if (top < 0 ) {
+ printf_console("Stack underflow\n");
+ return;
+ }
+ PUSH(sub_return_stack[top--]);
+}
+
/* words[] is a function array of all native code functions used by
* the dictionary, i.e. CFAs and primitives.
* Any change here needs a matching change in the primitive word's
@@ -1963,4 +1994,6 @@
do_encode_file, /* $encode-file */
do_debug_xt, /* (debug */
do_debug_off, /* (debug-off) */
+ sub_gt_r, /* sub_>r */
+ sub_r_gt /* sub_r> */
};
Index: libc/string.c
===================================================================
--- libc/string.c (revision 1391)
+++ libc/string.c (working copy)
@@ -385,3 +385,30 @@
return __res;
}
+// Search for a string within another string
+char *strstr(char *buffer, const char *search_string)
+{
+ if (!*search_string || (strlen(search_string) == 0)) {
+ return buffer;
+ }
+
+ int match_found, index, index2;
+ for (index = 0; index < strlen(buffer); index++) {
+ if (buffer[index] == search_string[0]) {
+ match_found = 1;
+ // see if we have a match
+ for (index2 = 0; index2 < strlen(search_string); index2++) {
+ if (buffer[index + index2] != search_string[index2]) {
+ match_found = 0; // match not found
+ break;
+ }
+ }
+ if(match_found == 1) {
+ return &buffer[index];
+ }
+ }
+ }
+
+ // Could not find search_string in buffer
+ return NULL;
+}
Index: libopenbios/bootinfo_load.c
===================================================================
--- libopenbios/bootinfo_load.c (revision 1391)
+++ libopenbios/bootinfo_load.c (working copy)
@@ -19,6 +19,7 @@
#include "libopenbios/bootinfo_load.h"
#include "libopenbios/ofmem.h"
#include "libc/vsprintf.h"
+#include "libc/string.h"
//#define DEBUG_BOOTINFO
@@ -116,6 +117,60 @@
return LOADER_NOT_SUPPORT;
}
+static void erase_memory(char *memory, int size)
+{
+ int i;
+ for(i = 0; i < size; i++) {
+ memory[i] = ' ';
+ }
+}
+
+// Replace all occurrences of orig_str in buffer with replace_str
+static void replace_string(char *buffer, const char *orig_str, const char *replace_str)
+{
+ char *ptr;
+ int index, new_buf_index = 0;
+ const int max_size = 5000;
+ char *new_buffer = malloc(max_size * sizeof(char));
+ erase_memory(new_buffer, max_size);
+
+ for (index = 0; index < strlen(buffer); index++) {
+ if (buffer[index] == orig_str[0]) {
+ ptr = strstr(buffer + index, orig_str);
+
+ // if we encountered an orig_str in the buffer
+ if (index == (ptr - buffer)) {
+ sprintf(new_buffer + new_buf_index, "%s ", replace_str);
+ new_buf_index += strlen(replace_str) + 1;
+ index += strlen(orig_str);
+ continue;
+ }
+ }
+ new_buffer[new_buf_index++] = buffer[index];
+ }
+
+ // Clear the origial buffer
+ erase_memory(buffer, max_size);
+
+ // copy new_buffer into buffer
+ for (index = 0; index < strlen(new_buffer); index++) {
+ buffer[index] = new_buffer[index];
+ }
+ buffer[index+1] = '\0';
+}
+
+/* Replace >r and r> with sub_>r and sub_r> */
+static void replace_return_stack_words(char *bootscript)
+{
+ const char *find_str1 = ">r";
+ const char *replace_str1 = "sub_>r";
+ const char *find_str2 = "r>";
+ const char *replace_str2 = "sub_r>";
+
+ replace_string(bootscript, find_str1, replace_str1);
+ replace_string(bootscript, find_str2, replace_str2);
+}
+
/*
Parse SGML structure like:
<chrp-boot>
@@ -190,8 +245,11 @@
while (current < size) {
c = base[current++];
+
+ if(c == '\r')
+ c = '\n';
- if (c == '<') {
+ if (c == '<') {
script = 0;
tag = 1;
taglen = 0;
@@ -262,6 +320,7 @@
/* If the payload is bootinfo then we execute it immediately */
if (scriptvalid) {
DPRINTF("bootscript: %s\n", bootscript);
+ replace_return_stack_words(bootscript);
feval(bootscript);
}
else
How do we increase the size of the dictionary? I thought it would be as simple as increasing the DICTIONARY_SIZE constant, but that causes this error:
ppc-elf-ld: section .romentry [00000000fffffffc -> 00000000ffffffff] overlaps section .data [00000000fff3c000 -> 000000010013c1d7]
ppc-elf-ld: openbios-qemu.elf.nostrip: section .romentry vma 0xfffffffc overlaps previous sections
On Apr 17, 2016, at 11:05 AM, Mark Cave-Ayland wrote:
> On 17/04/16 15:50, Programmingkid wrote:
>
>> Good news, I found out why replacing '\r' with '\n' works to boot Mac OS 9. It is because there are several words that require that character to be at the end of the line.
>>
>> http://www.complang.tuwien.ac.at/forth/1275.ps
>> This is the specifications to Open Firmware. Just do a search for EOL (End of Line a.k.a '\n'). You will see that several words need it in order to work.
>>
>> They will look like this:
>>
>> dev ( "device-specifier<eol>" -- )
>>
>> The <eol> text is what specifies that '\n' should be at the end of the line.
>
> Really? Interesting. Can you provide a self-contained test case that
> demonstrates that it is in fact the line ending that causes this
> independent of the r-stack manipulation? Bear in mind that OpenBIOS may
> deviate from the specification in its behaviour here.
Well I did a test but the results did not go as expected.
Index: libopenbios/bootinfo_load.c
===================================================================
--- libopenbios/bootinfo_load.c (revision 1395)
+++ libopenbios/bootinfo_load.c (working copy)
@@ -262,7 +262,8 @@
/* If the payload is bootinfo then we execute it immediately */
if (scriptvalid) {
DPRINTF("bootscript: %s\n", bootscript);
- feval(bootscript);
+ //feval(bootscript);
+ feval("dev /chosen\rcr pwd cr");
}
else
DPRINTF("Unable to parse bootinfo bootscript\n");
In the above code, if the '\r' was causing problems with dev, then this code would not have worked. The thing is it does work. It will print "/chosen" every time. My guess now is there is another word that is next to a '\r' character that can't handle that situation.
Author: mcayland
Date: Sun Apr 17 16:41:50 2016
New Revision: 1395
URL: http://tracker.coreboot.org/trac/openbios/changeset/1395
Log:
escc.c: add empty ranges property to escc and escc-legacy nodes
This fixes an intermittent panic in the AppleSCCSerial module for MacOS
10.2 and the g3beige machine during initialisation as the module tries to
write to the on-chip registers at 0x130XX rather than calculating the
correct address derived from the parent PCI node.
As described in the IEEE-1275 specification: if a "ranges" property exists but
has a zero-length property value, the child address space is identical to the
parent address space.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland(a)ilande.co.uk>
Modified:
trunk/openbios-devel/drivers/escc.c
Modified: trunk/openbios-devel/drivers/escc.c
==============================================================================
--- trunk/openbios-devel/drivers/escc.c Fri Mar 18 14:06:06 2016 (r1394)
+++ trunk/openbios-devel/drivers/escc.c Sun Apr 17 16:41:50 2016 (r1395)
@@ -514,6 +514,7 @@
set_property(dnode, "device_type", "escc",
strlen("escc") + 1);
set_property(dnode, "compatible", "escc\0CHRP,es0", 14);
+ set_property(dnode, "ranges", "", 0);
fword("finish-device");
@@ -541,6 +542,7 @@
set_property(dnode, "device_type", "escc-legacy",
strlen("escc-legacy") + 1);
set_property(dnode, "compatible", "chrp,es1", 9);
+ set_property(dnode, "ranges", "", 0);
fword("finish-device");
I made a program that tells what control characters are in the Mac OS ROM file. It reported that every single control character is in that file. Then I had it only look at the bootscript part. The carriage return and line feed characters are the only control characters found there.
http://www.ascii-code.com/
This page will tell you what the control characters are in case you don't know.
I added some code to the bootinfo_init_program() function in bootinfo_load.c file that changes all control characters to '\n'. This made Mac OS 9 boot. But when I changed the control characters to a single space, Mac OS 9 failed to boot. This seems strange to me. The space character is the ultimate whitespace character, so why would it fail when '\n' succeeds? My only guess right now is a bug with one of the words in Forth.
Here is the code I used. It is found around line 190 in the file:
while (current < size) {
c = base[current++];
// remove all control characters
if (c >= 0 && c <= 31) {
c = '\n';
}
if (c == '<') {
script = 0;
tag = 1;
taglen = 0;