amiga-bootcamp/02_boot_sequence/dos_boot.md
2026-04-26 14:46:18 -04:00

12 KiB
Raw Blame History

← Home · Boot Sequence

DOS Boot — Bootstrap, Boot Block, Mount List, Startup-Sequence

Overview

After the Kickstart ROM initializes the kernel and resident modules, the strap (bootstrap) module takes over. It enumerates bootable devices, reads and executes the boot block, mounts filesystems, and runs the user's startup scripts. This phase transitions the system from "kernel initialized" to "fully running desktop."


Architecture

graph TB
    subgraph "Phase 1: Device Enumeration"
        STRAP["strap module<br/>Priority -120"]
        ENUM["Enumerate boot devices<br/>Expansion boards + trackdisk"]
        SORT["Sort by boot priority<br/>(highest first)"]
    end

    subgraph "Phase 2: Boot Block"
        READ["Read sectors 0-1<br/>from boot device"]
        VALID["Validate:<br/>DOS\\x magic + checksum"]
        EXEC["Execute boot block code"]
    end

    subgraph "Phase 3: DOS Init"
        DOS["dos.library<br/>creates initial CLI process"]
        MOUNT["Mount devices<br/>DEVS:DOSDrivers/"]
        ASSIGN["SYS: = boot volume"]
    end

    subgraph "Phase 4: User Scripts"
        STARTUP["S:Startup-Sequence"]
        USER["S:User-Startup"]
        LOADWB["LoadWB<br/>→ Workbench desktop"]
    end

    STRAP --> ENUM
    ENUM --> SORT
    SORT --> READ
    READ --> VALID
    VALID -->|Valid| EXEC
    VALID -->|Invalid| NEXT["Try next device"]
    NEXT --> READ
    EXEC --> DOS
    DOS --> MOUNT
    MOUNT --> ASSIGN
    ASSIGN --> STARTUP
    STARTUP --> USER
    USER --> LOADWB

    style STRAP fill:#e8f4fd,stroke:#2196f3,color:#333
    style LOADWB fill:#e8f5e9,stroke:#4caf50,color:#333

Phase 1: The strap Module

The strap module (bootstrap) is the last resident initialized by Kickstart. It bridges ROM init and disk boot:

/* strap pseudo-code: */
void StrapInit(void)
{
    /* 1. Build list of bootable devices */
    struct BootNode *bootList = NULL;

    /* Check expansion boards (Zorro) for bootable devices */
    struct ConfigDev *cd = NULL;
    while ((cd = FindConfigDev(cd, -1, -1)) != NULL)
    {
        if (cd->cd_Flags & CDF_BOOTABLE)
        {
            /* Add to boot list with priority from RDB */
            AddBootNode(cd->cd_BootPri, cd->cd_BootFlags,
                        cd->cd_DeviceNode, cd->cd_ConfigDev);
        }
    }

    /* Always add DF0: (trackdisk unit 0, boot priority 5) */
    AddBootNode(5, 0, df0_DeviceNode, NULL);

    /* 2. Sort boot list by priority (highest first) */
    SortBootNodes(&bootList);

    /* 3. Try each device in order */
    struct BootNode *bn;
    for (bn = bootList; bn; bn = bn->bn_Next)
    {
        if (TryBootDevice(bn) == SUCCESS)
            break;  /* Booted successfully */
    }

    /* 4. If nothing bootable: "Insert Disk" screen */
    if (!bn)
        ShowInsertDiskScreen();
}

Boot Priority

Device Default Priority Source
DF0: 5 Hardcoded in trackdisk.device
DH0: 0 Set in RDB (Rigid Disk Block) partition table
DH1: 5 Set in RDB
DF1: 10 Hardcoded
CD0: 20 SCSI/IDE CD-ROM

Higher priority = tried first. A floppy in DF0: (pri 5) boots before a hard disk DH0: (pri 0) unless the hard disk partition has a higher boot priority set in HDToolBox.

Changing Boot Priority

; In HDToolBox:
;   1. Select partition → "Change..." → set Boot Priority
;   2. Priority > 5 = boots before floppy

; From CLI (OS 3.1+):
1> Assign SYS: DH0:
; (Does not change boot priority — only the current session)

Phase 2: Boot Block

Boot Block Format

The first 2 sectors (1024 bytes total) of a bootable disk:

Offset   Size   Field            Description
──────────────────────────────────────────────────
$000     4      DiskType         "DOS\0" through "DOS\7"
$004     4      Checksum         Ones' complement checksum of all 256 longwords
$008     4      RootBlock        Root block number (usually 880 for DD floppy)
$00C     1012   BootCode         68000 machine code — entry point at $00C

Disk Type Identifiers

ID Bytes String Hex Filesystem Features
444F5300 DOS\0 $00 OFS Original File System
444F5301 DOS\1 $01 FFS Fast File System
444F5302 DOS\2 $02 OFS+I OFS + International characters
444F5303 DOS\3 $03 FFS+I FFS + International characters
444F5304 DOS\4 $04 OFS+DC OFS + Directory Cache
444F5305 DOS\5 $05 FFS+DC FFS + Directory Cache
444F5306 DOS\6 $06 OFS+LFN OFS + Long Filenames (OS 3.2)
444F5307 DOS\7 $07 FFS+LFN FFS + Long Filenames (OS 3.2)
4B49434B KICK Kickstart disk A1000 WCS boot floppy
Non-DOS Custom Game/demo custom bootblock

Boot Block Checksum

/* Boot block checksum calculation */
ULONG ComputeBootChecksum(ULONG *block)
{
    ULONG sum = 0;
    ULONG saved = block[1];   /* Save current checksum */
    block[1] = 0;              /* Clear for calculation */

    for (int i = 0; i < 256; i++)   /* 256 longwords = 1024 bytes */
    {
        ULONG old = sum;
        sum += block[i];
        if (sum < old)         /* Carry */
            sum++;
    }

    block[1] = saved;          /* Restore */
    return ~sum;               /* Ones' complement */
}

/* Verify: */
if (ComputeBootChecksum(bootBlock) == bootBlock[1])
{
    /* Checksum valid — execute boot code */
}

Boot Block Execution

/* The strap module loads sectors 0-1 into Chip RAM and calls the code: */

/* Entry conditions for boot block code: */
/* A0 = pointer to boot block buffer in memory */
/* A1 = pointer to IOStdReq used to read the boot block */
/* A6 = SysBase (ExecBase) */
/* D0 = 0 */

/* The boot block code typically: */
/* 1. Finds dos.library */
/* 2. Calls dos.library's boot entry point */
/* Return value: 0 = success, non-zero = failure (try next device) */

Standard DOS Boot Block Code

; Standard AmigaDOS boot block (abbreviated):
BootEntry:
    LEA     DosName(PC),A1      ; "dos.library"
    JSR     -96(A6)              ; FindResident(A1) [exec LVO -96]
    TST.L   D0
    BEQ.S   .fail

    MOVE.L  D0,A0
    MOVE.L  22(A0),A0            ; rt_Init
    MOVEQ   #0,D0
    RTS                           ; Return to strap — which calls rt_Init

.fail:
    MOVEQ   #-1,D0
    RTS

DosName:
    DC.B    'dos.library',0
    EVEN

Custom Boot Blocks (Games/Demos)

Games bypass the standard boot block to take full control of the hardware:

; Typical game boot block:
BootEntry:
    ; Disable interrupts and DMA
    MOVE.W  #$7FFF,$DFF09A       ; INTENA = all off
    MOVE.W  #$7FFF,$DFF096       ; DMACON = all off

    ; Load the game's loader from disk
    LEA     $80000,A0            ; Destination in Chip RAM
    MOVEQ   #10,D0               ; Load 10 sectors
    BSR     ReadSectors           ; Custom disk reading routine

    ; Jump to game code
    JMP     $80000

; The game now has full hardware control — no OS running

Note

: Non-DOS boot blocks are why some games don't work with hard disk installers — they expect to take over the hardware immediately.


Phase 3: DOS Initialization

Once the standard boot block returns successfully, dos.library takes over:

Initial CLI Process

/* dos.library creates the initial CLI process: */
/* 1. Create a Process (struct Process) — the "Initial CLI" */
/* 2. Set up stdin/stdout to the boot console */
/* 3. Set SYS: assign to the boot volume */
/* 4. Set C:, S:, L:, LIBS:, DEVS:, FONTS: assigns */
/* 5. Execute S:Startup-Sequence */

Mount List Processing

Devices are mounted from two sources:

DEVS:MountList (Legacy)

/* DEVS:MountList format (text file): */
DH1:       Handler = L:FastFileSystem
           Priority = 5
           Stacksize = 4000
           GlobVec = -1
           BufMemType = 1
           Device = scsi.device
           Unit = 1
           Flags = 0
           Surfaces = 4
           BlocksPerTrack = 63
           LowCyl = 200
           HighCyl = 400
           Buffers = 50
           BootPri = -5
           DosType = 0x444F5301
#

DEVS:DOSDrivers/ (Modern — OS 2.0+)

Each file in DEVS:DOSDrivers/ is a mount specification for one device. These are auto-mounted at boot:

; DEVS:DOSDrivers/DH1 (icon file with tooltypes):
HANDLER  = L:FastFileSystem
DEVICE   = scsi.device
UNIT     = 1
FLAGS    = 0
SURFACES = 4
BLOCKSPERTRACK = 63
LOWCYL   = 200
HIGHCYL  = 400
BUFFERS  = 50
DOSTYPE  = 0x444F5301
BOOTPRI  = -5
STACKSIZE = 4000
GLOBVEC  = -1
ACTIVATE = 1

System Assigns

After mounting, the boot process sets up standard logical device assignments:

Assign Points To Purpose
SYS: Boot volume root System root
C: SYS:C System commands
S: SYS:S Scripts and startup files
L: SYS:L Handlers and loaders
LIBS: SYS:Libs Shared libraries
DEVS: SYS:Devs Device drivers and mount info
FONTS: SYS:Fonts System fonts
T: RAM:T Temporary files
CLIPS: RAM:Clipboards Clipboard data
ENV: RAM:ENV Environment variables (volatile)
ENVARC: SYS:Prefs/Env-Archive Env variables (persistent)

Phase 4: Startup-Sequence

Standard Startup-Sequence (OS 3.1)

; S:Startup-Sequence — master boot script
; Executed by the initial CLI process

C:SetPatch QUIET                  ; Apply ROM patches for this OS version
C:Version >NIL:                   ; Display version (redirected to NIL:)
FailAt 21                         ; Don't abort on warnings (error level < 21)

; Create RAM: directories
MakeDir RAM:T RAM:Clipboards RAM:ENV RAM:ENV/Sys

; Copy persistent environment to volatile RAM:
Copy >NIL: ENVARC: RAM:ENV ALL NOREQ

; Set up logical assignments
Assign >NIL: T:        RAM:T
Assign >NIL: CLIPS:    RAM:Clipboards
Assign >NIL: REXX:     S:
Assign >NIL: PRINTERS: DEVS:Printers
Assign >NIL: KEYMAPS:  DEVS:Keymaps
Assign >NIL: LOCALE:   SYS:Locale
Assign >NIL: LIBS:     SYS:Classes ADD
Assign >NIL: HELP:     LOCALE:Help DEFER

; Initialize preferences
C:IPrefs

; Start clipboard daemon
ConClip >NIL:

; Run user's custom startup
IF EXISTS S:User-Startup
    Execute S:User-Startup
ENDIF

; Launch Workbench
LoadWB

; End the initial CLI — Workbench takes over
EndCLI >NIL:

Startup-Sequence Commands Explained

Command Purpose
SetPatch Patches known bugs in ROM libraries for this OS version
FailAt 21 Continue script even if commands return warning codes (120)
Copy ENVARC: RAM:ENV Copy persistent prefs to fast volatile RAM for speed
IPrefs Apply system preferences (screen mode, fonts, palette, input)
ConClip Clipboard manager daemon — enables cut/paste between apps
LoadWB Start Workbench — opens the desktop, mounts icons
EndCLI Close the initial CLI window — Workbench is now primary UI

User-Startup

S:User-Startup is the user's personal script — runs after system init but before LoadWB:

; S:User-Startup — user customizations
Assign WORK: DH1:
Path SYS:Tools ADD
Path WORK:Bin ADD

; Start background daemons
Run >NIL: C:CrossDOS
Run >NIL: C:PCTaskX

; Load custom keymaps
SetKeyboard usa1

Error Handling During Boot

Error Symptom Recovery
No bootable disk "Insert Disk" animation Insert bootable floppy in DF0:
Bad boot block checksum Skips device, tries next Fix boot block with Install command
dos.library not found Guru Meditation Corrupted ROM — reflash
Startup-Sequence error CLI prompt with error message Fix script manually
Assign to missing volume "Please insert volume X" requester Insert disk or skip
LoadWB fails CLI remains visible Check SYS:System/Workbench exists

Emergency Recovery

; Boot with no Startup-Sequence (hold both mouse buttons):
;   → Early Startup Control → "Boot With No Startup-Sequence"
;   → Get a CLI prompt with SYS: mounted

; Fix corrupt startup:
1> ED S:Startup-Sequence

; Reinstall boot block:
1> Install DF0:
; or for hard disk:
1> Install DH0:

References

  • NDK39: dos/dosextens.h, dos/filehandler.h
  • ADCD 2.1: BootStrap, AddBootNode, MakeDosEntry
  • See also: Kickstart Init — what happens before strap
  • See also: Early Startup — boot menu options
  • See also: Filesystem — FFS/OFS block layout
  • Amiga ROM Kernel Reference Manual: Exec — boot chapter