mirror of
https://github.com/alfishe/amiga-bootcamp.git
synced 2026-06-12 16:16:28 +00:00
251 lines
8.2 KiB
Markdown
251 lines
8.2 KiB
Markdown
[← Home](../README.md) · [Exec Kernel](README.md)
|
||
|
||
# ExecBase — Full Structure Reference
|
||
|
||
## Overview
|
||
|
||
`ExecBase` is the root structure of AmigaOS, located at absolute address `$4`. It is a `struct Library` extended with all exec kernel state: memory lists, task queues, interrupt vectors, library lists, and hardware abstraction fields. Every system call goes through `ExecBase` — it is the single point of truth for the entire running system.
|
||
|
||
---
|
||
|
||
## Locating ExecBase
|
||
|
||
```c
|
||
/* C — standard method */
|
||
struct ExecBase *SysBase = *((struct ExecBase **)4);
|
||
|
||
/* Or use the auto-open variable (SAS/C, GCC): */
|
||
extern struct ExecBase *SysBase; /* Linker resolves from startup code */
|
||
```
|
||
|
||
```asm
|
||
; Assembly — canonical method
|
||
MOVEA.L 4.W,A6 ; A6 = SysBase (short absolute addressing)
|
||
; All exec LVO calls use JSR offset(A6)
|
||
```
|
||
|
||
> **Why address $4?** The 68000 stores the initial Program Counter at address $4 in the exception vector table. During cold boot, the CPU reads this address to find the ROM entry point. After boot, Exec overwrites it with a pointer to ExecBase. This is the one absolute address every Amiga program can rely on.
|
||
|
||
---
|
||
|
||
## Structure Layout
|
||
|
||
```mermaid
|
||
graph TB
|
||
EB["ExecBase at $4"] --> LIB["Library Header<br/>(struct Library)<br/>Offsets 0–33"]
|
||
EB --> SOFT["Software Config<br/>SoftVer, ColdCapture,<br/>WarmCapture, SysStkUpper"]
|
||
EB --> TASK["Task Scheduling<br/>TaskReady, TaskWait,<br/>ThisTask, IDNestCnt,<br/>TDNestCnt, Quantum"]
|
||
EB --> MEM["Memory Management<br/>MemList, MaxLocMem,<br/>MaxExtMem"]
|
||
EB --> LISTS["System Lists<br/>LibList, DeviceList,<br/>ResourceList, PortList,<br/>IntrList"]
|
||
EB --> HW["Hardware Detection<br/>AttnFlags, ChipRevBits0,<br/>PowerSupplyFrequency,<br/>VBlankFrequency"]
|
||
|
||
style EB fill:#e8f4fd,stroke:#2196f3,color:#333
|
||
style TASK fill:#e8f5e9,stroke:#4caf50,color:#333
|
||
style HW fill:#fff3e0,stroke:#ff9800,color:#333
|
||
```
|
||
|
||
---
|
||
|
||
## Key Field Groups
|
||
|
||
### Library Header (Offset 0–33)
|
||
|
||
Every library starts with this — ExecBase is exec.library's own base:
|
||
|
||
```c
|
||
struct Library LibNode; /* ln_Name = "exec.library" */
|
||
/* lib_Version = 40 (OS 3.1), 45 (OS 3.2), 47 (OS 3.2.2) */
|
||
/* lib_OpenCnt = open count */
|
||
```
|
||
|
||
### Boot and Configuration
|
||
|
||
| Offset | Field | Type | Description |
|
||
|---|---|---|---|
|
||
| `$22` | `SoftVer` | `UWORD` | Kickstart software revision |
|
||
| `$24` | `LowMemChkSum` | `WORD` | Checksum of vectors $0–$200 |
|
||
| `$26` | `ChkBase` | `ULONG` | ExecBase self-checksum |
|
||
| `$2A` | `ColdCapture` | `APTR` | Cold reboot intercept vector |
|
||
| `$2E` | `CoolCapture` | `APTR` | Warm reboot intercept vector (after Diag) |
|
||
| `$32` | `WarmCapture` | `APTR` | Keyboard reset intercept vector |
|
||
| `$36` | `SysStkUpper` | `APTR` | Top of supervisor stack |
|
||
| `$3A` | `SysStkLower` | `APTR` | Bottom of supervisor stack |
|
||
| `$3E` | `MaxLocMem` | `ULONG` | Top of Chip RAM (e.g., `$200000` for 2 MB) |
|
||
| `$42` | `DebugEntry` | `APTR` | Entry point for ROM debugger (Wack) |
|
||
| `$46` | `DebugData` | `APTR` | Data area for ROM debugger |
|
||
| `$4A` | `AlertData` | `APTR` | Last Alert data |
|
||
| `$4E` | `MaxExtMem` | `APTR` | Top of Extended RAM (or NULL) |
|
||
|
||
### Task Scheduling
|
||
|
||
| Offset | Field | Type | Description |
|
||
|---|---|---|---|
|
||
| `$126` | `IDNestCnt` | `BYTE` | Interrupt disable nesting (−1 = enabled) |
|
||
| `$127` | `TDNestCnt` | `BYTE` | Task disable nesting (−1 = enabled) |
|
||
| `$128` | `ThisTask` | `APTR` | Pointer to currently running Task |
|
||
| `$12C` | `Quantum` | `UWORD` | Time slice for equal-priority round-robin |
|
||
| `$12E` | `Elapsed` | `UWORD` | Ticks elapsed in current quantum |
|
||
| `$130` | `SysFlags` | `UWORD` | Internal scheduler flags |
|
||
| `$132` | `TaskReady` | `List` | Tasks ready to run (sorted by priority) |
|
||
| `$146` | `TaskWait` | `List` | Tasks blocked on `Wait()` |
|
||
|
||
### Memory
|
||
|
||
| Offset | Field | Type | Description |
|
||
|---|---|---|---|
|
||
| `$15A` | `MemList` | `List` | All memory regions (`MemHeader` chain) |
|
||
|
||
### System Lists
|
||
|
||
| Offset | Field | Type | Description |
|
||
|---|---|---|---|
|
||
| `$17A` | `LibList` | `List` | Loaded libraries (`NT_LIBRARY`) |
|
||
| `$18E` | `DeviceList` | `List` | Loaded devices (`NT_DEVICE`) |
|
||
| `$1A2` | `IntrList` | `List` | Interrupt server lists |
|
||
| `$1B6` | `ResourceList` | `List` | System resources |
|
||
| `$1CA` | `PortList` | `List` | Public message ports |
|
||
| `$1DE` | `SemaphoreList` | `List` | Public semaphores |
|
||
|
||
### Hardware Detection
|
||
|
||
| Offset | Field | Type | Description |
|
||
|---|---|---|---|
|
||
| `$128` | `AttnFlags` | `UWORD` | CPU and FPU capability flags |
|
||
| `$212` | `VBlankFrequency` | `UBYTE` | VBL rate: 50 (PAL) or 60 (NTSC) |
|
||
| `$213` | `PowerSupplyFrequency` | `UBYTE` | Mains: 50 or 60 Hz |
|
||
| `$21E` | `ChipRevBits0` | `UBYTE` | Chip revision detection |
|
||
|
||
---
|
||
|
||
## AttnFlags — CPU Detection
|
||
|
||
| Bit | Constant | Meaning |
|
||
|---|---|---|
|
||
| 0 | `AFF_68010` | 68010 or better detected |
|
||
| 1 | `AFF_68020` | 68020 or better |
|
||
| 2 | `AFF_68030` | 68030 or better |
|
||
| 3 | `AFF_68040` | 68040 or better |
|
||
| 4 | `AFF_68881` | 68881 FPU detected |
|
||
| 5 | `AFF_68882` | 68882 FPU detected |
|
||
| 6 | `AFF_FPU40` | 68040 internal FPU |
|
||
| 7 | `AFF_68060` | 68060 detected (OS 3.1+) |
|
||
| 10 | `AFF_PRIVATE` | Exec private — do not use |
|
||
|
||
### Usage
|
||
|
||
```c
|
||
/* Check for 68020+ */
|
||
if (SysBase->AttnFlags & AFF_68020)
|
||
{
|
||
/* Can use CACHE instructions, 32-bit multiply, etc. */
|
||
}
|
||
|
||
/* Check for FPU */
|
||
if (SysBase->AttnFlags & (AFF_68881 | AFF_68882 | AFF_FPU40))
|
||
{
|
||
/* Floating-point hardware available */
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Detecting Chipset Revision
|
||
|
||
```c
|
||
/* via graphics.library */
|
||
struct GfxBase *gfx = (struct GfxBase *)OpenLibrary("graphics.library", 36);
|
||
if (gfx)
|
||
{
|
||
if (gfx->ChipRevBits0 & GFXB_AA_ALICE) /* AGA Alice */
|
||
if (gfx->ChipRevBits0 & GFXB_AA_LISA) /* AGA Lisa */
|
||
if (gfx->ChipRevBits0 & GFXB_HR_AGNUS) /* ECS Agnus */
|
||
if (gfx->ChipRevBits0 & GFXB_HR_DENISE) /* ECS Denise */
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Enumerating System Lists
|
||
|
||
### Walking the Library List
|
||
|
||
```c
|
||
Forbid();
|
||
struct Node *node;
|
||
for (node = SysBase->LibList.lh_Head;
|
||
node->ln_Succ != NULL;
|
||
node = node->ln_Succ)
|
||
{
|
||
struct Library *lib = (struct Library *)node;
|
||
Printf(" %s V%ld.%ld (open: %ld)\n",
|
||
lib->lib_Node.ln_Name,
|
||
lib->lib_Version,
|
||
lib->lib_Revision,
|
||
lib->lib_OpenCnt);
|
||
}
|
||
Permit();
|
||
```
|
||
|
||
### Walking the Task Lists
|
||
|
||
```c
|
||
Forbid();
|
||
|
||
/* Currently running */
|
||
Printf("Running: %s\n", SysBase->ThisTask->tc_Node.ln_Name);
|
||
|
||
/* Ready to run */
|
||
for (node = SysBase->TaskReady.lh_Head;
|
||
node->ln_Succ; node = node->ln_Succ)
|
||
{
|
||
Printf(" Ready: %s (pri %ld)\n",
|
||
node->ln_Name, node->ln_Pri);
|
||
}
|
||
|
||
/* Waiting */
|
||
for (node = SysBase->TaskWait.lh_Head;
|
||
node->ln_Succ; node = node->ln_Succ)
|
||
{
|
||
Printf(" Wait: %s (pri %ld)\n",
|
||
node->ln_Name, node->ln_Pri);
|
||
}
|
||
|
||
Permit();
|
||
```
|
||
|
||
---
|
||
|
||
## ExecBase Safety Rules
|
||
|
||
| Rule | Reason |
|
||
|---|---|
|
||
| **Never write to ExecBase fields** | Corrupts kernel state for all tasks |
|
||
| **Use `Forbid()` when walking lists** | Lists change as libraries open/close, tasks start/stop |
|
||
| **Don't cache pointers from lists** | Nodes may be removed between accesses |
|
||
| **Always use LVO functions** | Direct field manipulation bypasses safety checks |
|
||
| **Verify `SysBase` after warm reboot** | `ColdCapture`/`CoolCapture` may have altered it |
|
||
|
||
---
|
||
|
||
## ExecBase in IDA Pro / Ghidra
|
||
|
||
After loading Kickstart ROM:
|
||
|
||
1. **Create a segment** at `$000000–$000400` (exception vectors)
|
||
2. **Mark `$4` as a pointer** — follow it to the ExecBase in ROM
|
||
3. **Apply `struct ExecBase` type** from NDK39 headers
|
||
- IDA: `File → Parse C header` with `exec/execbase.h`
|
||
- Ghidra: Import C headers via Data Type Manager
|
||
4. **All `N(A6)` offsets** in exec code auto-annotate as field names
|
||
5. **Label the system lists** — `LibList`, `DeviceList`, `PortList` are entry points for understanding boot order
|
||
|
||
---
|
||
|
||
## References
|
||
|
||
- NDK39: `exec/execbase.h` — authoritative field definitions
|
||
- ADCD 2.1: exec.library autodoc
|
||
- See also: [Library System](library_system.md) — how libraries relate to ExecBase
|
||
- See also: [Multitasking](multitasking.md) — TaskReady/TaskWait and scheduler internals
|
||
- See also: [Kickstart Boot Diagnostics](../02_boot_sequence/kickstart-boot-diagnostics.md) — ColdStart ExecBase allocation, chip RAM sizing
|
||
- *Amiga ROM Kernel Reference Manual: Exec* — ExecBase chapter
|