From 4f2c11a06b5824adc2025d979c45e4043329ae0a Mon Sep 17 00:00:00 2001 From: MCJack123 Date: Mon, 29 Jul 2024 02:33:19 -0400 Subject: [PATCH 1/3] stage1: Add Old World loading capabilities This is untested, as I don't have a G3 beige system, but the same process works on my OF 1.0.5 PM7600. --- README.md | 13 +- arcgrackle/Makefile | 2 +- arcloader_grackle/Makefile | 28 +++- arcloader_grackle/hack-coff.c | 79 +++++++++++ arcloader_grackle/of-xcoff.ld | 27 ++++ arcloader_grackle/rs6000.h | 243 ++++++++++++++++++++++++++++++++++ 6 files changed, 385 insertions(+), 7 deletions(-) create mode 100644 arcloader_grackle/hack-coff.c create mode 100644 arcloader_grackle/of-xcoff.ld create mode 100644 arcloader_grackle/rs6000.h diff --git a/README.md b/README.md index 0068569..3359500 100644 --- a/README.md +++ b/README.md @@ -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"* @@ -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. @@ -73,6 +71,11 @@ 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). ## Known issues @@ -96,11 +99,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. diff --git a/arcgrackle/Makefile b/arcgrackle/Makefile index b201b81..945b164 100644 --- a/arcgrackle/Makefile +++ b/arcgrackle/Makefile @@ -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) diff --git a/arcloader_grackle/Makefile b/arcloader_grackle/Makefile index eae9942..2833726 100644 --- a/arcloader_grackle/Makefile +++ b/arcloader_grackle/Makefile @@ -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) @@ -33,11 +37,14 @@ OBJCOPY = $(PREFIX)objcopy RANLIB = $(PREFIX)ranlib STRIP = $(PREFIX)strip +HOSTCC ?= gcc + ifeq ($(NOMAPFILE),) LDFLAGS += -Wl,-Map,$(TARGET).map endif ifneq ($(LDSCRIPT),) +LDFLAGS_XCOFF += -Wl,-T$(LDSCRIPT_XCOFF) LDFLAGS += -Wl,-T$(LDSCRIPT) endif @@ -46,11 +53,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) diff --git a/arcloader_grackle/hack-coff.c b/arcloader_grackle/hack-coff.c new file mode 100644 index 0000000..a25db53 --- /dev/null +++ b/arcloader_grackle/hack-coff.c @@ -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 +#include +#include +#include +#include + +#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); +} \ No newline at end of file diff --git a/arcloader_grackle/of-xcoff.ld b/arcloader_grackle/of-xcoff.ld new file mode 100644 index 0000000..35aef7b --- /dev/null +++ b/arcloader_grackle/of-xcoff.ld @@ -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 = .; +} \ No newline at end of file diff --git a/arcloader_grackle/rs6000.h b/arcloader_grackle/rs6000.h new file mode 100644 index 0000000..ecff59e --- /dev/null +++ b/arcloader_grackle/rs6000.h @@ -0,0 +1,243 @@ +/* IBM RS/6000 "XCOFF" file definitions for BFD. + Copyright (C) 1990, 1991 Free Software Foundation, Inc. + FIXME: Can someone provide a transliteration of this name into ASCII? + Using the following chars caused a compiler warning on HIUX (so I replaced + them with octal escapes), and isn't useful without an understanding of what + character set it is. + Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM + and John Gilmore of Cygnus Support. */ + +/********************** FILE HEADER **********************/ + +struct external_filehdr { + char f_magic[2]; /* magic number */ + char f_nscns[2]; /* number of sections */ + char f_timdat[4]; /* time & date stamp */ + char f_symptr[4]; /* file pointer to symtab */ + char f_nsyms[4]; /* number of symtab entries */ + char f_opthdr[2]; /* sizeof(optional hdr) */ + char f_flags[2]; /* flags */ +}; + + /* IBM RS/6000 */ +#define U802WRMAGIC 0730 /* writeable text segments **chh** */ +#define U802ROMAGIC 0735 /* readonly sharable text segments */ +#define U802TOCMAGIC 0737 /* readonly text segments and TOC */ + +#define BADMAG(x) \ + ((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \ + (x).f_magic != U802TOCMAGIC) + +#define FILHDR struct external_filehdr +#define FILHSZ 20 + + +/********************** AOUT "OPTIONAL HEADER" **********************/ + + +typedef struct +{ + unsigned char magic[2]; /* type of file */ + unsigned char vstamp[2]; /* version stamp */ + unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */ + unsigned char dsize[4]; /* initialized data " " */ + unsigned char bsize[4]; /* uninitialized data " " */ + unsigned char entry[4]; /* entry pt. */ + unsigned char text_start[4]; /* base of text used for this file */ + unsigned char data_start[4]; /* base of data used for this file */ + unsigned char o_toc[4]; /* address of TOC */ + unsigned char o_snentry[2]; /* section number of entry point */ + unsigned char o_sntext[2]; /* section number of .text section */ + unsigned char o_sndata[2]; /* section number of .data section */ + unsigned char o_sntoc[2]; /* section number of TOC */ + unsigned char o_snloader[2]; /* section number of .loader section */ + unsigned char o_snbss[2]; /* section number of .bss section */ + unsigned char o_algntext[2]; /* .text alignment */ + unsigned char o_algndata[2]; /* .data alignment */ + unsigned char o_modtype[2]; /* module type (??) */ + unsigned char o_cputype[2]; /* cpu type */ + unsigned char o_maxstack[4]; /* max stack size (??) */ + unsigned char o_maxdata[4]; /* max data size (??) */ + unsigned char o_resv2[12]; /* reserved */ +} +AOUTHDR; + +#define AOUTSZ 72 +#define SMALL_AOUTSZ (28) +#define AOUTHDRSZ 72 + +#define RS6K_AOUTHDR_OMAGIC 0x0107 /* old: text & data writeable */ +#define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */ +#define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */ + + +/********************** SECTION HEADER **********************/ + + +struct external_scnhdr { + char s_name[8]; /* section name */ + char s_paddr[4]; /* physical address, aliased s_nlib */ + char s_vaddr[4]; /* virtual address */ + char s_size[4]; /* section size */ + char s_scnptr[4]; /* file ptr to raw data for section */ + char s_relptr[4]; /* file ptr to relocation */ + char s_lnnoptr[4]; /* file ptr to line numbers */ + char s_nreloc[2]; /* number of relocation entries */ + char s_nlnno[2]; /* number of line number entries*/ + char s_flags[4]; /* flags */ +}; + +/* + * names of "special" sections + */ +#define _TEXT ".text" +#define _DATA ".data" +#define _BSS ".bss" +#define _PAD ".pad" +#define _LOADER ".loader" + +#define SCNHDR struct external_scnhdr +#define SCNHSZ 40 + +/* XCOFF uses a special .loader section with type STYP_LOADER. */ +#define STYP_LOADER 0x1000 + +/* XCOFF uses a special .debug section with type STYP_DEBUG. */ +#define STYP_DEBUG 0x2000 + +/* XCOFF handles line number or relocation overflow by creating + another section header with STYP_OVRFLO set. */ +#define STYP_OVRFLO 0x8000 + +/********************** LINE NUMBERS **********************/ + +/* 1 line number entry for every "breakpointable" source line in a section. + * Line numbers are grouped on a per function basis; first entry in a function + * grouping will have l_lnno = 0 and in place of physical address will be the + * symbol table index of the function name. + */ +struct external_lineno { + union { + char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/ + char l_paddr[4]; /* (physical) address of line number */ + } l_addr; + char l_lnno[2]; /* line number */ +}; + + +#define LINENO struct external_lineno +#define LINESZ 6 + + +/********************** SYMBOLS **********************/ + +#define E_SYMNMLEN 8 /* # characters in a symbol name */ +#define E_FILNMLEN 14 /* # characters in a file name */ +#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ + +struct external_syment +{ + union { + char e_name[E_SYMNMLEN]; + struct { + char e_zeroes[4]; + char e_offset[4]; + } e; + } e; + char e_value[4]; + char e_scnum[2]; + char e_type[2]; + char e_sclass[1]; + char e_numaux[1]; +}; + + + +#define N_BTMASK (017) +#define N_TMASK (060) +#define N_BTSHFT (4) +#define N_TSHIFT (2) + + +union external_auxent { + struct { + char x_tagndx[4]; /* str, un, or enum tag indx */ + union { + struct { + char x_lnno[2]; /* declaration line number */ + char x_size[2]; /* str/union/array size */ + } x_lnsz; + char x_fsize[4]; /* size of function */ + } x_misc; + union { + struct { /* if ISFCN, tag, or .bb */ + char x_lnnoptr[4]; /* ptr to fcn line # */ + char x_endndx[4]; /* entry ndx past block end */ + } x_fcn; + struct { /* if ISARY, up to 4 dimen. */ + char x_dimen[E_DIMNUM][2]; + } x_ary; + } x_fcnary; + char x_tvndx[2]; /* tv index */ + } x_sym; + + union { + char x_fname[E_FILNMLEN]; + struct { + char x_zeroes[4]; + char x_offset[4]; + } x_n; + } x_file; + + struct { + char x_scnlen[4]; /* section length */ + char x_nreloc[2]; /* # relocation entries */ + char x_nlinno[2]; /* # line numbers */ + } x_scn; + + struct { + char x_tvfill[4]; /* tv fill value */ + char x_tvlen[2]; /* length of .tv */ + char x_tvran[2][2]; /* tv range */ + } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ + + struct { + unsigned char x_scnlen[4]; + unsigned char x_parmhash[4]; + unsigned char x_snhash[2]; + unsigned char x_smtyp[1]; + unsigned char x_smclas[1]; + unsigned char x_stab[4]; + unsigned char x_snstab[2]; + } x_csect; + +}; + +#define SYMENT struct external_syment +#define SYMESZ 18 +#define AUXENT union external_auxent +#define AUXESZ 18 +#define DBXMASK 0x80 /* for dbx storage mask */ +#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK) + + + +/********************** RELOCATION DIRECTIVES **********************/ + + +struct external_reloc { + char r_vaddr[4]; + char r_symndx[4]; + char r_size[1]; + char r_type[1]; +}; + + +#define RELOC struct external_reloc +#define RELSZ 10 + +#define DEFAULT_DATA_SECTION_ALIGNMENT 4 +#define DEFAULT_BSS_SECTION_ALIGNMENT 4 +#define DEFAULT_TEXT_SECTION_ALIGNMENT 4 +/* For new sections we havn't heard of before */ +#define DEFAULT_SECTION_ALIGNMENT 4 \ No newline at end of file From c8d8b6c4b59a785f91c22c93e18516f748661978 Mon Sep 17 00:00:00 2001 From: MCJack123 Date: Mon, 29 Jul 2024 02:58:48 -0400 Subject: [PATCH 2/3] stage1(Makefile): fix build for oldworld --- arcloader_grackle/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arcloader_grackle/Makefile b/arcloader_grackle/Makefile index 2833726..003a51d 100644 --- a/arcloader_grackle/Makefile +++ b/arcloader_grackle/Makefile @@ -20,7 +20,7 @@ LDSCRIPT = of.ld TARGET = stage1.elf LDSCRIPT_XCOFF = of-xcoff.ld -LDFLAGS_XCOFF = $(LDFLAGS) +LDFLAGS_XCOFF := $(LDFLAGS) TARGET_XCOFF = boot FILES = $(wildcard source/*.S) $(wildcard source/*.c) @@ -40,6 +40,7 @@ STRIP = $(PREFIX)strip HOSTCC ?= gcc ifeq ($(NOMAPFILE),) +LDFLAGS_XCOFF += -Wl,-Map,$(TARGET_XCOFF).map LDFLAGS += -Wl,-Map,$(TARGET).map endif From 3e1b7ec493ecad935774b1d4bf4cec2ca9acdcd5 Mon Sep 17 00:00:00 2001 From: MCJack123 Date: Tue, 30 Jul 2024 18:07:01 -0400 Subject: [PATCH 3/3] readme: add attribution, System Disk info --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3359500..b3394c9 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ NT 3.51 RTM and higher. NT 3.51 betas (build 944 and below) will need kernel pat * 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 @@ -116,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.