mirror of
https://github.com/alfishe/amiga-bootcamp.git
synced 2026-06-13 00:26:28 +00:00
docs(amiga): complete AmigaOS 3.1/3.2 developer reference — 172 files across 17 sections
Comprehensive technical documentation covering: - Hardware: OCS/ECS/AGA custom chip registers, Copper & Blitter deep dives - Boot sequence: cold boot through startup-sequence - Binary format: HUNK executable spec, relocation, debug info - Linking & ABI: .fd files, LVO tables, register calling conventions - Exec kernel: tasks, interrupts, memory, signals, semaphores - AmigaDOS: file I/O, FFS/OFS layout, CLI/Shell scripting - Graphics: planar bitmaps, Copper programming, HAM/EHB modes - Intuition: screens, windows, IDCMP, BOOPSI - Devices: trackdisk, SCSI, serial, timer, audio, keyboard - Libraries: utility, expansion, IFFParse, locale, ARexx - Networking: bsdsocket API, SANA-II, TCP/IP stack comparison - Toolchain: GCC, vasm/vlink, SAS/C, NDK, debugging - Reverse engineering: IDA/Ghidra setup, compiler fingerprints, case studies - CPU & MMU: 68040/060 emulation libs, PMMU, cache management - Driver development: SANA-II, Picasso96/RTG, AHI audio All files include breadcrumb navigation. No local paths or proprietary content.
This commit is contained in:
parent
f07a368bf1
commit
21751c0025
172 changed files with 19701 additions and 0 deletions
129
05_reversing/case_studies/ramdrive_device.md
Normal file
129
05_reversing/case_studies/ramdrive_device.md
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
[← Home](../../README.md) · [Reverse Engineering](../README.md)
|
||||
|
||||
# Case Study — ramdrive.device Structure Analysis
|
||||
|
||||
## Overview
|
||||
|
||||
`ramdrive.device` is the Amiga's built-in RAM disk device. It ships in Kickstart ROM and implements the `trackdisk.device`-compatible interface on top of allocated Chip/Fast RAM. Analysing it teaches exec device architecture, IORequest handling, and the device-as-library pattern.
|
||||
|
||||
---
|
||||
|
||||
## Locating ramdrive.device in ROM
|
||||
|
||||
```bash
|
||||
# Find the resident tag in Kickstart ROM dump:
|
||||
python3 - <<'EOF'
|
||||
import struct, sys
|
||||
|
||||
rom = open("kick31.rom", "rb").read()
|
||||
for i in range(0, len(rom)-4, 2):
|
||||
tag = struct.unpack_from(">H", rom, i)[0]
|
||||
if tag == 0x4AFC: # RomTag magic
|
||||
rt_matchword = struct.unpack_from(">H", rom, i)[0]
|
||||
rt_matchtag = struct.unpack_from(">I", rom, i+2)[0]
|
||||
rt_name = struct.unpack_from(">I", rom, i+14)[0]
|
||||
# print offset and map rt_name to string
|
||||
print(f"RomTag @ ROM+{i:#x}")
|
||||
EOF
|
||||
```
|
||||
|
||||
The RomTag for `ramdrive.device` has `RT_TYPE=NT_DEVICE` and `RT_NAME="ramdrive.device"`.
|
||||
|
||||
---
|
||||
|
||||
## Device Structure Layout
|
||||
|
||||
`ramdrive.device` extends `struct Device` (which extends `struct Library`):
|
||||
|
||||
```c
|
||||
struct RAMDriveBase {
|
||||
struct Device rd_Device; /* standard device base */
|
||||
/* private fields follow */
|
||||
APTR rd_RAMStart; /* pointer to allocated RAM block */
|
||||
ULONG rd_RAMSize; /* total size */
|
||||
ULONG rd_BlockSize; /* always 512 */
|
||||
ULONG rd_NumBlocks; /* RAMSize / BlockSize */
|
||||
struct MinList rd_Units; /* list of open units */
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Standard Device Vectors (LVO)
|
||||
|
||||
| Offset | Vector | Description |
|
||||
|---|---|---|
|
||||
| −6 | `Open` | Open a unit (unit number in io_Unit) |
|
||||
| −12 | `Close` | Close unit, decrement open count |
|
||||
| −18 | `Expunge` | Unload if no users |
|
||||
| −24 | `Reserved` | NULL |
|
||||
| −30 | `BeginIO` | Queue or execute an IORequest |
|
||||
| −36 | `AbortIO` | Cancel pending IORequest |
|
||||
|
||||
`BeginIO` is the heart of any device driver — it dispatches on `io_Command`.
|
||||
|
||||
---
|
||||
|
||||
## IORequest Command Handling
|
||||
|
||||
```c
|
||||
void BeginIO(struct IORequest *ior) {
|
||||
struct IOStdReq *io = (struct IOStdReq *)ior;
|
||||
switch (io->io_Command) {
|
||||
case CMD_READ: rd_Read(io); break;
|
||||
case CMD_WRITE: rd_Write(io); break;
|
||||
case CMD_CLEAR: rd_Clear(io); break;
|
||||
case TD_FORMAT: rd_Format(io); break;
|
||||
case TD_GETGEOMETRY: rd_Geometry(io); break;
|
||||
default:
|
||||
io->io_Error = IOERR_NOCMD;
|
||||
ReplyMsg(&io->io_Message);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `CMD_READ` Implementation
|
||||
|
||||
```c
|
||||
void rd_Read(struct IOStdReq *io) {
|
||||
UBYTE *src = rdbase->rd_RAMStart + io->io_Offset;
|
||||
CopyMem(src, io->io_Data, io->io_Length);
|
||||
io->io_Actual = io->io_Length;
|
||||
io->io_Error = 0;
|
||||
ReplyMsg(&io->io_Message);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Memory Allocation Strategy
|
||||
|
||||
On initialisation, `ramdrive.device` uses `AllocMem`:
|
||||
|
||||
```c
|
||||
rdbase->rd_RAMStart = AllocMem(rdbase->rd_RAMSize,
|
||||
MEMF_PUBLIC | MEMF_CLEAR);
|
||||
```
|
||||
|
||||
Later requests can pass `MEMF_CHIP` to force chip RAM allocation (useful for audio/graphics DMA sources).
|
||||
|
||||
---
|
||||
|
||||
## Disassembly Landmarks in IDA
|
||||
|
||||
After loading Kickstart ROM in IDA with M68k + HUNK/ROM loader:
|
||||
|
||||
1. Search for string `"ramdrive.device"` → find RomTag
|
||||
2. `RT_INIT` pointer → initialization function
|
||||
3. `RT_INIT` calls `MakeLibrary` then `AddDevice`
|
||||
4. The device base is stored — follow to find `BeginIO` function
|
||||
5. `BeginIO` switch table → individual command handlers
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- NDK39: `exec/devices.h`, `exec/io.h`, `devices/trackdisk.h`
|
||||
- `06_exec_os/io_requests.md` — IORequest structure and dispatch
|
||||
- `10_devices/trackdisk_device.md` — TD_* command codes
|
||||
- Kickstart 3.1 ROM dump (required for disassembly)
|
||||
Loading…
Add table
Add a link
Reference in a new issue