You are on page 1of 10

Reconstructing the Leftovers on the Amiga

Kickstart 1.0 Disk


Michael Steil, pagetable.com

It is well-known that the Kickstart disk that came with the


original Amiga 1000 in 1985 contained some fragments of
source code: The floppy disk that was used as a master for
duplication had been used by the developers before, and
had not been erased completely.
Nobody seemed to have looked too closely at what is on this disk - so I did,
for this episode of Computer Archeology. The revealed data tells us about
how the Amiga operating system was brought up, how it related to Tripos,
and where it was developed.

The Kickstart Disk


When the Amiga 1000 was released, the 1.0 ROM image was not finalized,
so the machine shipped with a Kickstart floppy disk that was loaded into
an extra 256 KB RAM bank which was then write-protected.
A double-density Amiga disk is exactly 880 KB, i.e. it consists of 1760 sectors, each 512 bytes in size. The Kickstart disk has a header on sector 0
(saying KICK followed by all zero bytes), and the raw ROM image is stored
on the following sectors. The ROM is 256 KB in size, so this means that all
sectors from 513 on are unused, and, in the case of the Kickstart 1.0 disk,
preserved.
The following analysis has been done on the Kickstart 1.0 ADF disk image
with an MD5 of 2fb28e7bbab0d2eef00e742c7259a674.

Amiga Old Filesystem


Before version 1.3 of the operating system, disks were formatted with the
Amiga Old Filesystem, which was quite inefficient, as it stored metadata
pretty redundantly. Every single sector, even sectors containing file data,
start with a 24 byte header, which contains
1.

the type of the sector (directory entry, data)

2.

a pointer to the parent

3.

the sequence number of the sector inside the file

4.

the number of valid bytes in the sector

5.

a pointer to the successor

6.

and a checksum.

Michael Steil: Reconstructing the Leftovers on the Amiga Kickstart 1.0 Disk
Every directory entry occupies a complete sector, and deleting a file means
just removing the links to the directory entry sector, without touching the
data sectors or the directory entry sector at all. And whats best: For performance reasons, directory entries are clustered around the center of the
disk, i.e. sector 880, which, in our case, has not been overwritten by the
ROM image, so it should be easy to get some data out of this disk.

Extraction Program
The program to extract the data from the disk uses the following algorithm:
It iterates over all sectors from the end of the ROM image to the end of the
disk image and looks at the sector type. If it is a data block, it looks at the
parent, in the hope that it is an intact directory entry. If this is the case, it
walks back the list from parent to parent to get the full path and filename
of the file. If the directory entry has not survived, the file will get the index
of the directory entry as a name. As we now know the filename of the file
the sector belongs to and we can read the sequence number from the sector header, it is possible to write 488 bytes worth of data into the output
file.
Here is the source code of the program to extract the files: extract-adf.c

Results
The disk seemed to have contained C header files and assembly includes
earlier, and has then been overwritten with the current set of command line
tools of AmigaOS (the name of the disk cli26.1 reflects this), extended
with some custom development tools used by Commodore-Amiga.
Since the DOS part of the Amiga operating system is actually based on the
only very slightly modified Metacomco Tripos operating system, the command line tools as well as the development tools mentioned in the following sections are mostly the same as those found in Tripos; therefore the
terms Tripos and AmigaDOS may be used interchangeably.

CLI Programs
The c subdirectory contains the following command line tools that can
also be found on the Workbench 1.0 disk:
Assign

Echo

If

Prompt

Stack

Break

Ed

Info

Protect

Status

CD

Edit

Install

Quit

Type

Copy

EndCLI

Join

Rename

Wait

Date

Execute

Lab

Run

Why

Delete

FailAt

List

Search

Dir

Fault

MakeDir

Skip

NewCLI

Sort

DiskCopy Format

The following executables can be found in the l directory:


2

Michael Steil: Reconstructing the Leftovers on the Amiga Kickstart 1.0 Disk
Disk-Validator
Port-Handler
Ram-Handler

But these may very well be earlier versions. DiskCopy for example is significantly smaller than the Diskcopy that shipped with Workbench 1.0.

Development Tools
The following command line utilities can also be found in c. They do not
ship with WorkBench, but are part of a separtare tools disk for developers,
as described in the AmigaDOS Manual. Some also exist on pre-1.0 beta
versions of Workbench, although possibly in different versions.
Alink

Amiga Linker Version 2.17, Copyright (C) 1985 by Tenchstar Ltd.,


T/A Metacomco.

DiskEd

AmigaDOS Disc Editor

Down-

DownLoad version 2.0, Sun->Amiga transfer utility

Load
DumpObj

Displays executable hunks in hex

Alink is the Amiga-native version of the TRIPOS/Metacomco linker


According to the AmigaDOS Manual (or Tripos Technial Reference Manual),
to inspect or patch disk blocks, you may use the AmigaDOS [Tripos] disk
editor, DISKED. The version on this disk is 3.2; the 2.0+ NDKs shipped
with 3.4, and cintpos, the open source release of Tripos, includes the
source for 3.0.
Download is quite interesting, not only because the binary and its documentation are very hard to find, but also because they tell a lot about the
history of the Amiga operating system. According to the AmigaDOS manual,
it is used to download programs written on another computer (for example, a Sun) to the Amiga. - the counterpart on the Sun workstation would
be binload.
An interesting side note on this version of Download is that it still contains all linker symbols, and has a debugging mode (-d) that prints out
every step that it is doing, so it is pretty easy to reverse-engineer.
There is strong evidence that the Amiga operating system has been cross
developed on Sun machines. After all, the official Amiga SDK is called
NDK, Native Development Kit, implying that the original bringup SDK
was not native.
At that time (1985), Sun Workstations were 68000- or 68010-based computers running SunOS 1.x, which was based on 4.1BSD. The C compiler that
came with BSD at that time was the Bell Labs Portable C Compiler (PCC),
which could naturally output 68000 code. The Bell Labs C compiler (i.e.
3

Michael Steil: Reconstructing the Leftovers on the Amiga Kickstart 1.0 Disk
PCC) is mentioned in a header file in the Native Development Kit for AmigaOS as printed in AMIGA ROM Kernel Reference Manual: Libraries and Devices, next to the suggested native compiler Lattice C and two other
compilers, implying that PCC could be used for Amiga development.
The AmigaDOS manual says that the tools available on the Sun Microsystem for cross development include the assembler, linker, and two C compilers. One compiler is explicitly mentioned: It is the Greenhills C compiler (metacc; the name suggests it was Metacomcos shipping C compiler
for Tripos); the other one is presumably PCC. According to this resume, the
first versions of the ROM were compiled using the Greenhills C compiler.
So Commodore-Amiga must have cross-developed AmigaOS on BSD with
the Greenhills C compiler.

New Executables
c/d
c/Read

serial/parallel port receiving utility

c/ReadPref

accesses config/preferences

demos/ImageEdit

d seems to be used to delete files, Read contains strings about reading


from serial and parallel ports, ReadPrefs accesses the file config/
preferences, which is also included on this disk. It is unknown what ImageEdit is for - it does not contain any strings, but included linker symbols
imply that it deals with timers.

Devices and Libraries


The disk also comes with the Narrator device and the Translator library,
which are required for speech synthesis. These two files have been overwritten once, so there are now two different copies on the disk:
devs/narrator.device

narrator Version 25 (rev 3) (Thu Jun 20 18:47:53 PDT


1985)

devs/narrator.device

narrator Version 26 (rev 1) (Wed Jun 19 14:22:29 PDT


1985)

libs/translator.library

translator Version 26 (rev 1) (Wed Jun 19 14:49:56


PDT 1985)

libs/translator.library

translator Version 26 (rev 5) (Thu Jun 20 17:25:49


PDT 1985)

The header of the libraries contain the respective versions. Note that the
newer version of narrator.device has the older timestamp. PDT implies
that AmigaOS has been written on the US West Coast - in the California office of Commodore. For comparison, Workbench 1.0 shipped with
narrator 1.6 (10 Sep 1985)
translator 1.3 (4 Sep 1985)

Michael Steil: Reconstructing the Leftovers on the Amiga Kickstart 1.0 Disk

Misc Files
config/preferences

240 bytes, mostly 0s, no strings, read by c/


ReadPrefs

s/startup-sequence

ReadPref
echo Use the DATE command to set date and time
wait 1 sec
date

t/ed-backupequence

echo Use the DATE command to set date and time


wait 1 sec
date

This is an ED backup of startup-sequence


demos/src/wtest.asm

Assembly source in Metacomco format (MOVE.L;


for assem) that prints Hello World to the console
and opens a window. The source has been generated
with metacc -S.

Files for Development


For many of the files on the disk, the original directory entry has been lost,
but it was possible to reconstruct the filename using the printed headers in
AMIGA ROM Kernel Reference Manual: Libraries and Devices, digital versions of older and newer versions of the headers, and the AROS versions of
the headers.
Sector Filename

Comment

935

C wrapper code around the Amiga APIs


(first few sectors missing)

amiga.lib

1077 crt0.obj

Linker object that contains the code that


gets executed before main(). It opens
dos.library, caches stdin and stdout, and
provides an exit() function.

1074 clib/macros.h
1025 exec/alerts.h

(first few sectors missing)

1026 exec/execname.h
1045 graphics/clip.h

02-04-85 Dale created file from graph.h

1050 graphics/clip.i
1051 graphics/collide.h

8-24-84 Dale added this header file

1052 graphics/copper.h

2-09-85 Dale made #defines for union ignorance

1053 graphics/display.h

8-24-84 Dale added this header file

1054 graphics/gels.h

9-28-84 -=RJ=- for GELS16 added Bob.h to


this file

Michael Steil: Reconstructing the Leftovers on the Amiga Kickstart 1.0 Disk
1055 graphics/gels.i
1056 graphics/gfx.h

Feb

85

Dale

added

Rectangle,BitMap

structures

1057 graphics/gfx.i
1048 graphics/gfxbase.h

10-20-84 Kodiak added this header file &


TextFonts

1059 graphics/gfxbase.i
1060 graphics/gfxmacros.h

9-07-84

Dale

fixed

macros

to

use

new

RastPort

1061 graphics/graphint.h
1062 graphics/layers.h
1063 graphics/layers.i
1064 graphics/rastport.h

02-04-85 Dale created from graph.h

1065 graphics/rastport.i
1058 graphics/regions.h
1066 graphics/regions.i
1067 graphics/sprite.h
1068 graphics/sprite.i
1 0 2 7 graphics/text.i
1071

$Header: text.i,v 25.1 85/05/06 10:54:07


kodiak Exp $

(version at 1027: first few sectors missing)


1 0 2 8 graphics/text.h
1069

$Header: text.h,v 25.1 85/05/06 10:53:57


kodiak Exp $

(two identical copies)


1072 graphics/view.h

2-8-85

Dale

conversion

to

24

View-

>ViewPort

1073 graphics/view.i
1044 intuition/intuition.h 1-30-85 -=RJ=- created this file!
1047 intuition/intuition.i 6-13-85 =VoodooDrRj= added back the comments

1046 intuition/intuitionba 3-1-85 -=RJ=- created this file!


se.h

1009 libraries/translator.h
1029 libraries/translator.i
1030 libraries/dos.h
1032 libraries/dos.i
1033 libraries/dosextens.h
1034 libraries/dosextens.i
1035 libraries/mathffp.h

Michael Steil: Reconstructing the Leftovers on the Amiga Kickstart 1.0 Disk
1036 resources/cia.i
1043 resources/ciabase.i
1041 resources/disk.i

$Header: disk.i,v 26.1 85/06/17 12:19:27


neil Exp $

1042 resources/disk.h

$Header: disk.h,v 26.2 85/06/17 13:01:21


neil Exp $

1038 resources/potgo.h
1031 resources/potgo.i
1039 resources/misc.i

$Header: misc.i,v 26.1 85/06/17 12:08:29


neil Exp $

1040 resources/misc.h

$Header: misc.h,v 26.1 85/06/17 12:08:26


neil Exp $

1070 diag/romdiag.i

only came with 1.0 of the includes

Unlike the published NDK headers, these still contain the revision control
and author information. All files use UNIX line breaks (LF).
Some files contain the address of Commodore-Amiga, which was:
Commodore-Amiga Incorporated
983 University Ave. Building #D
Los Gatos, California, 95030

Directory Entries with Missing Data


There are directory entries for the following header files and includes on
the disk, but the data is missing
devices/audio.h
devices/audio.i
devices/bootblock.h
devices/bootblock.i
devices/console.h
devices/console.i
devices/gameport.h
devices/gameport.i
devices/inputevent.h
devices/inputevent.i
devices/keyboard.h
devices/keyboard.i
devices/keymap.h
devices/keymap.i
devices/narrator.h
devices/narrator.i
devices/parallel.h
devices/parallel.i
devices/serial.h

Michael Steil: Reconstructing the Leftovers on the Amiga Kickstart 1.0 Disk
devices/serial.i
devices/timer.h
devices/timer.i
devices/trackdisk.h
devices/trackdisk.i
hardware/blit.i
hardware/intbits.h

There are four more directory entries for executable files:


Assem

AmigaDOS/Tripos macro assembler by Metacomco.

Avail

shipped with developer tools, and OS >= 1.3

ObjDump

probably same as DumpObj

SetPref

probably the counterpart to ReadPref

Conclusion
The following conclusions can be drawn from this exercise:
1.

The reduncandy in the Amiga Old Filesystem makes this filesystem perfect
for reconstructing deleted and even partially overwritten data.

2.

AmigaOS seems to have been bootstrapped using SunOS and the


Metacomco/Tripos toolchain, and has probably not been self-hosting for
1.0.

3.

The disk was used to move developer tools and header files between machines.

4.

Version 1.0 of the OS has been developed in the California office of Commodore - the original Amiga office.

Open Questions
1.

What source control system was used?

2.

How does the version numbering (26.1 etc.) work? How is it related to
source control?

3.

Does the 1.0 NDK still exist somewhere? It should have shipped with Lattice
C, at least. It would be very interesting to compare these headers and includes with the 1.0 NDK ones; for real differences, and for changes in the
comments.

4.

What are the differences between these headers and the 1.0 headers? Any
last minute changes?

Links
http://gega.homelinux.net/AmigaDevDocs/

Michael Steil: Reconstructing the Leftovers on the Amiga Kickstart 1.0 Disk
/*
* extract-adf.c
* (C)2008 Michael Steil, http://www.pagetable.com/
* Do whatever you want with it, but please give credit.
*/
#include <libc.h>
#include <sys/_endian.h>
#define SECTORS 1760
#define FIRST_SECTOR 513 /* for kick10.adf */
#define
#define
#define

T_HEADER 2
T_DATA 8
T_LIST 16

typedef unsigned int uint32_t;


struct sector_raw {

uint8_t byte[512];
};
struct blkhdr {

uint32_t

uint32_t

uint32_t

uint32_t

uint32_t

uint32_t
};

type;
header_key;
seq_num;
data_size;
next_data;
chksum;

struct fileheader {

struct blkhdr hdr;

uint8_t misc[288];

uint32_t unused1;

uint16_t uid;

uint16_t gid;

uint32_t protect;

uint32_t byte_size;

uint8_t comm_len;

uint8_t comment[79];

uint8_t unused2[12];

uint32_t days;

uint32_t mins;

uint32_t ticks;

uint8_t name_len;

char filename[30];

uint8_t unused3;

uint32_t unused4;

uint32_t real_entry;

uint32_t next_link;

uint32_t unused5[5];

uint32_t hash_chain;

uint32_t parent;

uint32_t extension;

uint32_t sec_type;
};
struct dataheader {

struct blkhdr hdr;

uint8_t data[488];
};
union sector {

struct blkhdr hdr;

struct fileheader fh;

struct dataheader dh;
};
#define DATABYTES (sizeof(union sector)-sizeof(struct blkhdr))
union sector sector[SECTORS];
void printfilename(int i) {

if (ntohl(sector[i].hdr.type) != T_HEADER)


return;

if (sector[i].fh.parent) {


printfilename(ntohl(sector[i].fh.parent));

}

printf("/%s", sector[i].fh.filename);
}
int main() {

FILE *f;

int i, j;

uint32_t type, header_key;

char filename[31];


f = fopen("kick10.adf", "r");

int r = fread(sector, sizeof(union sector), SECTORS, f);

printf("sectors: %d\n", r);

fclose(f);












for (i=FIRST_SECTOR; i<SECTORS; i++) {



type = ntohl(sector[i].hdr.type);

if (type != T_HEADER && type != T_DATA && type != T_LIST)


continue;

printf("%x: type
%x\n", i, ntohl(sector[i].hdr.type));

printf("%x: header_key %x\n", i, ntohl(sector[i].hdr.header_key));

printf("%x: seq_num
%x\n", i, ntohl(sector[i].hdr.seq_num));

printf("%x: data_size %x\n", i, ntohl(sector[i].hdr.data_size));

printf("%x: next_data %x\n", i, ntohl(sector[i].hdr.next_data));

printf("%x: chksum
%x\n", i, ntohl(sector[i].hdr.chksum));

switch (type) {


case T_HEADER:



printf("%x: filename \"%s\"\n", i, sector[i].fh.filename);

Michael Steil: Reconstructing the Leftovers on the Amiga Kickstart 1.0 Disk











//
























}



printf("%x: byte_size %d\n", i, ntohl(sector[i].fh.byte_size));


break;

case T_DATA:


header_key = ntohl(sector[i].hdr.header_key);


if (header_key<SECTORS && ntohl(sector[header_key].hdr.type) == T_HEADER) {



printf("%x: filename \"%s\"\n", i, sector[header_key].fh.filename);



printf("%x: byte_size %d\n", i, ntohl(sector[header_key].fh.byte_size));



strncpy(filename, sector[header_key].fh.filename, sizeof(filename));


} else {



snprintf(filename, sizeof(filename), "%04d.txt", header_key);


}


printf("XXX \"%s\" %03d: ", filename, ntohl(sector[i].hdr.seq_num));


printf("XXX \"");


printfilename(header_key);


printf("\" %03d: ", ntohl(sector[i].hdr.seq_num));


for (j=0; j<16; j++) {



uint8_t c = sector[i].dh.data[j];



if ((c>=32 && c<128)||c==9) {




printf("%c", c);



} else {




printf("<0x%02x>", c);



}


}


printf("\n");


f = fopen(filename, "r+"); /* try to open existing file */


if (!f)



f = fopen(filename, "w"); /* doesn't exist, so create */


fseek(f, (ntohl(sector[i].hdr.seq_num)-1)*DATABYTES, SEEK_SET);


printf("seek to %ld\n", (ntohl(sector[i].hdr.seq_num)-1)*DATABYTES);


fwrite(sector[i].dh.data, ntohl(sector[i].hdr.data_size), 1, f);


fclose(f);
}
printf("\n");

return 0;

10