[go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Old World loading capabilities #31

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ This repository currently contains the source code for the ARC firmware and its
* Power Macintosh G3 (Blue & White) *"Yosemite"*
* Macintosh PowerBook G3 Bronze Keyboard *"Lombard"*
* Power Macintosh G4 PCI *"Yikes!"*

The ARC firmware itself runs at a low enough level that it should be compatible with Old World systems using the same chipset too, but there is currently no loader for these systems; these are the following:

* Power Macintosh G3 (beige)
* Macintosh PowerBook G3 Series *"Wallstreet"*, *"PDQ"*

Expand Down Expand Up @@ -45,6 +42,7 @@ NT 3.51 RTM and higher. NT 3.51 betas (build 944 and below) will need kernel pat
### Partitioning Disk

* Boot your PowerMac from the burned optical media. When you get to ARC firmware menu, go to `Run firmware setup`, then `Repartition disk for NT installation`.
* On an "Old World" machine (Power Mac G3 beige, PowerBook G3 Wallstreet/PDQ), boot the CD by holding Cmd+Opt+O+F to enter Open Firmware, type `boot ide1/disk\boot.xcf`, and press enter.
* The disk partitioner will first let you enter partition size of the NT partition (up to the 16383x16x63 CHS limit, minus 32 MB ARC system partition + 1 MB for partition tables / MBR backup / OS 9 drivers / ARC environment variable storage, giving a maximum possible size of 8030 MB), then will drop to a menu allowing the creation of additional Mac partitions.
* If you choose an NT partition size over 2GB, the partition will be formatted to NTFS.
* After adding a partition to the list, the only way to remove from the list is by cancelling the operation and starting the partitioner again.
Expand Down Expand Up @@ -73,6 +71,12 @@ NT 3.51 RTM and higher. NT 3.51 betas (build 944 and below) will need kernel pat
* If you chose to create an NT partition of over 2GB in size, errors will be found by the disk examination process which will require a reboot. Boot your PowerMac from the ARC firmware CD again and follow the steps to boot the NT4 text setup again.
* On the second attempt, disk examination will succeed, so just choose the `C:` partition again in the NT text setup partition selector.
* Proceed through the rest of NT text and graphical setup as normal.
* On an Old World system, you'll need to set the boot device manually.
* Reboot and hold Cmd+Opt+O+F to enter Open Firmware.
* Type `setenv boot-device ide0/disk@0:6\boot.xcf` to set the boot device.
* Type `reset-all` or press Ctrl+Cmd+Power to restart.
* You'll need to do this again if the PRAM gets reset (e.g. power is removed and PRAM battery is dead or removed).
* If you have Mac OS 8/9 working, you can also use the System Disk control panel to set the boot device. Select the `Power User` option, and select `Configure Manually` next to `Boot Device`. Then change it to `ide0/disk@0:6\boot.xcf` as shown above. Hit `Save` and reboot.

## Known issues

Expand All @@ -96,11 +100,11 @@ You need devkitPPC. Additionally, a `libgcc.a` compiled for `powerpcle` must be

* Ensure `DEVKITPPC` environment variable is set to your devkitPPC directory, usually `/opt/devkitpro/devkitPPC`
* Build the big endian libc: `cd baselibc ; make ; cd ..`
* Build the ARC firmware loader: `cd arcloader_grackle ; make ; cd ..`
* Build the ARC firmware loader: `cd arcloader_grackle ; make ; make oldworld ; cd ..`
* Build the little endian libc: `cd arcgrackle/baselibc ; make ; cd ../..`
* Build the ARC firmware itself: `cd arcgrackle ; make ; cd ..`

Replace `stage1.elf` and `stage2.elf` inside the release image. For recreating the image from a folder dump, use your preferred tool to create a hybrid HFS+ISO image, make sure `System` folder is blessed and `BootX` file is of type `tbxi`.
Replace `stage1.elf`, `boot.xcf`, and `stage2.elf` inside the release image. For recreating the image from a folder dump, use your preferred tool to create a hybrid HFS+ISO image, make sure `System` folder is blessed and `BootX` file is of type `tbxi`.

Please note that `stage1.elf` must not be larger than 16KB and `stage2.elf` must not be larger than 224KB.

Expand All @@ -113,3 +117,4 @@ Please note that `stage1.elf` must not be larger than 16KB and `stage2.elf` must
* USB drivers in OpenBIOS were themselves adapted from [coreboot](https://github.com/coreboot/coreboot)
* ISO9660 FS implementation inside ARC firmware is [lib9660](https://github.com/erincandescent/lib9660) with some modifications.
* FAT FS implementation inside ARC firmware is [Petit FatFs](http://elm-chan.org/fsw/ff/00index_p.html) with some modifications.
* `hack-coff.c` for XCOFF loaders is borrowed from the Linux kernel source.
2 changes: 1 addition & 1 deletion arcgrackle/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ $(TARGET): $(OBJS)
@echo " LINK $@"
@$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
@cp $(TARGET) $(TARGET:%.elf=%_unstripped.elf)
@strip $(TARGET)
@$(STRIP) $(TARGET)

ifneq ($(LDSCRIPT),)
$(TARGET): $(LDSCRIPT)
Expand Down
29 changes: 28 additions & 1 deletion arcloader_grackle/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ LDFLAGS += -nostartfiles -nodefaultlibs -L../baselibc
LDSCRIPT = of.ld
TARGET = stage1.elf

LDSCRIPT_XCOFF = of-xcoff.ld
LDFLAGS_XCOFF := $(LDFLAGS)
TARGET_XCOFF = boot

FILES = $(wildcard source/*.S) $(wildcard source/*.c)
OBJSx = $(FILES:source/%.S=build/%.o)
OBJS = $(OBJSx:source/%.c=build/%.o)
Expand All @@ -33,11 +37,15 @@ OBJCOPY = $(PREFIX)objcopy
RANLIB = $(PREFIX)ranlib
STRIP = $(PREFIX)strip

HOSTCC ?= gcc

ifeq ($(NOMAPFILE),)
LDFLAGS_XCOFF += -Wl,-Map,$(TARGET_XCOFF).map
LDFLAGS += -Wl,-Map,$(TARGET).map
endif

ifneq ($(LDSCRIPT),)
LDFLAGS_XCOFF += -Wl,-T$(LDSCRIPT_XCOFF)
LDFLAGS += -Wl,-T$(LDSCRIPT)
endif

Expand All @@ -46,11 +54,30 @@ DEPDIR = .deps
all: $(TARGET)
@[ -d $(DIR_BUILD) ] || mkdir $(DIR_BUILD)

oldworld: $(TARGET_XCOFF).xcf
@[ -d $(DIR_BUILD) ] || mkdir $(DIR_BUILD)

$(TARGET): $(OBJS)
@echo " LINK $@"
@$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
@cp $(TARGET) $(TARGET:%.elf=%_unstripped.elf)
@strip $(TARGET)
@$(STRIP) $(TARGET)

$(TARGET_XCOFF).elf: $(OBJS)
@echo " LINK $@"
@$(CC) $(LDFLAGS_XCOFF) $(OBJS) $(LIBS) -o $@
@cp $(TARGET_XCOFF).elf $(TARGET_XCOFF)_unstripped.elf
@$(STRIP) $(TARGET_XCOFF).elf

$(TARGET_XCOFF).xcf: $(TARGET_XCOFF).elf hack-coff
@echo " OBJCOPY $@"
@rm -f $@
@$(OBJCOPY) -O aixcoff-rs6000 -j .text -j .data -j .bss $< $@
@./hack-coff $@

hack-coff: hack-coff.c
@echo " HOSTCC $@"
@$(HOSTCC) -o $@ $<

ifneq ($(LDSCRIPT),)
$(TARGET): $(LDSCRIPT)
Expand Down
79 changes: 79 additions & 0 deletions arcloader_grackle/hack-coff.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* hack-coff.c - hack the header of an xcoff file to fill in
* a few fields needed by the Open Firmware xcoff loader on
* Power Macs but not initialized by objcopy.
*
* Copyright (C) Paul Mackerras 1997.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include "rs6000.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define AOUT_MAGIC 0x010b

#define get_16be(x) ((((unsigned char *)(x))[0] << 8) + ((unsigned char *)(x))[1])
#define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, ((unsigned char *)(x))[1] = (v) & 0xff)
#define get_32be(x) ((((unsigned char *)(x))[0] << 24) + (((unsigned char *)(x))[1] << 16) + (((unsigned char *)(x))[2] << 8) + ((unsigned char *)(x))[3])

int main(int ac, char **av) {
int fd;
int i, nsect;
int aoutsz;
struct external_filehdr fhdr;
AOUTHDR aout;
struct external_scnhdr shdr;

if (ac != 2) {
fprintf(stderr, "Usage: hack-coff coff-file\n");
exit(1);
}
if ((fd = open(av[1], 2)) == -1) {
perror(av[2]);
exit(1);
}
if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr)) goto readerr;
i = get_16be(fhdr.f_magic);
if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) {
fprintf(stderr, "%s: not an xcoff file\n", av[1]);
exit(1);
}
aoutsz = get_16be(fhdr.f_opthdr);
if (read(fd, &aout, aoutsz) != aoutsz) goto readerr;
put_16be(aout.o_sndata, 0);
put_16be(aout.o_snbss, 0);
put_16be(aout.o_sntext, 0);
put_16be(aout.o_sntoc, 0);
put_16be(aout.o_snentry, 0);
put_16be(aout.o_snloader, 0);
nsect = get_16be(fhdr.f_nscns);
for (i = 0; i < nsect; ++i) {
if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) goto readerr;
if (strcmp(shdr.s_name, ".text") == 0) {
put_16be(aout.o_sntext, i + 1);
put_16be(aout.o_snentry, i + 1);
} else if (strcmp(shdr.s_name, ".data") == 0) {
put_16be(aout.o_sndata, i + 1);
} else if (strcmp(shdr.s_name, ".bss") == 0) {
put_16be(aout.o_snbss, i + 1);
}
}
put_16be(aout.magic, AOUT_MAGIC);
if (lseek(fd, (long)sizeof(struct external_filehdr), 0) == -1 || write(fd, &aout, aoutsz) != aoutsz) {
fprintf(stderr, "%s: write error\n", av[1]);
exit(1);
}
close(fd);
exit(0);

readerr:
fprintf(stderr, "%s: read error or file too short\n", av[1]);
exit(1);
}
27 changes: 27 additions & 0 deletions arcloader_grackle/of-xcoff.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
OUTPUT_FORMAT("elf32-powerpc")
OUTPUT_ARCH(powerpc:common)

ENTRY(StartAixCall)

SECTIONS {
. = 0x00050000;
__text_start = .;

.text : { *(.text) *(.text.*) *(.rodata) KEEP(*(.rodata.StartAixCall)); *(.rodata.*) }

. = ALIGN(4);

.sdata : { *(.sdata) *(.sdata.*) }
.data : { *(.data) *(.data.*) }

. = ALIGN(32);
__self_end = .;

__bss_start = .;
.bss : { *(.bss .bss.*) } :NONE = 0
.sbss : { *(.sbss) }
__bss_end = .;

. = ALIGN(32);
_end = .;
}
Loading