Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ATAPI CD-ROM + ISO 9660 (boot-time reader)

This is a provenance map for the boot-time CD-ROM read path: it cites the specs, summarizes only the wire-format subset the code actually implements, and points into the implementation. It is not a re-spec. Unlike the PCI/virtio device pages, this is a legacy port-I/O hardware transport used only during boot or install-source proofs to read ELF/package bytes from an ISO; the capOS-mapping section reflects its boot-only, kernel-owned status. The boot source itself is planned CD-ROM/ISO support, not a deprecated path. The driver is concise and feature-gated (boot_iso_read / boot_iso), so the treatment is a short map rather than exhaustive register tables.

The whole reader lives in kernel/src/iso/mod.rs.

1. Spec basis

  • Device: ATAPI CD-ROM on a legacy IDE (Parallel ATA) channel, accessed by polled PIO over the legacy I/O ports. Not a PCI/virtio device and not enumerated through PCI; the two legacy channels are probed at fixed port bases (PRIMARY_CMD/PRIMARY_CTRL 0x1F0/0x3F6, SECONDARY_CMD/SECONDARY_CTRL 0x170/0x376). QEMU’s -cdrom shorthand attaches the disc on the secondary channel (master), which AtapiDevice::probe scans first.
  • Authoritative specs:
    • ATA Packet Interface — the PACKET command transport and the ATA/ATAPI register protocol, as standardized in the SFF-8020i / ATA/ATAPI-4+ family (INCITS T13). The PACKET data-in handshake, the ATAPI signature in the cylinder-low/high (LBA mid/high) registers, and the READ(12) / READ CAPACITY(10) command-descriptor blocks come from this basis. The signature the driver matches is ATAPI_SIG_MID (0x14) in the LBA-mid register and ATAPI_SIG_HIGH (0xEB) in the LBA-high register.
    • ECMA-119 (equivalently ISO 9660), Volume and File Structure of CDROM for Information Interchange — the volume-descriptor and directory-record on-disk layout the IsoFs parser indexes. The relevant structures are the primary volume descriptor (PVD) and the directory record.
  • Reference: the legacy IDE/ATAPI PIO sequence and the ISO 9660 fixed-offset field layout are the well-documented OSDev-wiki “ATAPI”/“ISO 9660” baseline; cross-checked against the QEMU IDE/ATAPI device behavior the proofs run against.

2. Wire format (implemented subset)

Only the polled-PIO read subset the driver uses is summarized; ATA features the driver never issues (DMA transfers, write commands, the full SCSI command set) are not implemented and are not transcribed here.

ATAPI PACKET read path

  • Channel register map: command-block register offsets relative to the channel command base — REG_DATA (0), REG_FEATURES (1), REG_SECCOUNT (2), REG_LBA_LOW (3), REG_LBA_MID (4), REG_LBA_HIGH (5), REG_DRIVE (6), REG_STATUS/REG_COMMAND (7). In the ATAPI PACKET protocol REG_LBA_MID / REG_LBA_HIGH carry the byte-count low/high for the data phase, not an LBA.
  • Status / control bits: STATUS_BSY (0x80), STATUS_DRQ (0x08), STATUS_ERR (0x01); control-block CTRL_NIEN (0x02, interrupts disabled — this path is polled only) and CTRL_SRST (0x04, soft reset in soft_reset). Drive select is DRIVE_MASTER (0xA0) / DRIVE_SLAVE (0xB0).
  • Probe / detect: AtapiDevice::probe soft-resets each channel and calls detect, which selects a drive and matches the ATAPI_SIG_MID / ATAPI_SIG_HIGH signature; a 0xFF status is treated as a floating (empty) bus. Every status spin is bounded by SPIN_LIMIT (wait_not_busy / wait_drq), so an absent or wedged device fails closed rather than hanging boot.
  • PACKET command issue (AtapiDevice::packet_data_in): writes CMD_PACKET (0xA0) to the command register, programs the per-block byte-count limit BYTE_LIMIT (2048, one CD logical sector) into the LBA mid/high registers, waits for DRQ, then writes the 12-byte command-descriptor block (CDB) as six 16-bit words. The data-in phase reads each DRQ block, taking its byte count from the LBA mid/high registers; it rejects a byte count over BYTE_LIMIT, an odd byte count, or one that would overflow the destination buffer (IsoError::Protocol / BufferTooSmall).
  • CDBs implemented: CDB_READ12 (0xA8) with the big-endian LBA at bytes 2..6 and transfer length at bytes 6..10 (built in AtapiDevice::read_sectors), and CDB_READ_CAPACITY10 (0x25, in AtapiDevice::read_capacity) returning the last addressable LBA and the logical block size. A reported block size is range-checked against MIN_BLOCK_SIZE (2048) / MAX_BLOCK_SIZE (4096).
  • Bounded sector read (AtapiDevice::read_sectors): rejects a zero count, arithmetic overflow (IsoError::InvalidRequest), an LBA range past the reported capacity (OutOfRange), and a destination buffer shorter than count * block_size (BufferTooSmall), all before any device access. A device that returns fewer bytes than requested is rejected (ShortRead).

ISO 9660 volume structure

  • Primary volume descriptor: IsoFs::mount reads PVD_LBA (sector 16, after the reserved system area) through read_sectors and validates the descriptor type (pvd[0] == 1), the CD001 standard identifier (pvd[1..6]), and the version (pvd[6] == 1). ISO 9660 stores integers both-endian (a little-endian half followed by a big-endian half); the driver reads the little-endian half with le_u16 / le_u32. It indexes the logical block size (both-endian u16 at offset 128, which must equal the device block size), the volume space size (both-endian u32 at offset 80), and the embedded root directory record (34-byte MIN_DIR_RECORD at offset 156, whose extent LBA is bytes 2..6 and size bytes 10..14).
  • Directory records: IsoFs::lookup / list_boot_bins walk a directory extent record by record. Each record’s length is byte 0 (a zero length skips to the next logical-sector boundary); the file-flags byte 25 carries FILE_FLAG_DIR (0x02); the file-identifier length is byte 32 and the identifier starts at byte 33; the extent LBA/size are bytes 2..6 / 10..14. The ./.. self/parent records (identifier 0x00/0x01) are skipped, and identifiers are matched case-insensitively after stripping the ;version suffix and trailing dots (name_matches / normalize_ident).
  • Path resolution: IsoFs::lookup_path descends from the root through each component; boot_bins_dir resolves /boot/bins/ and open_file resolves a named file beneath it, each returning a validated (lba, size) extent.

3. capOS mapping

  • Binding (boot-only, kernel-owned): this is not a DDF device. It is not enumerated through PCI and does not bind through the DeviceMmio/Interrupt/DMAPool provider grants the cloud-NIC/storage drivers use; it owns fixed legacy I/O ports directly in kernel mode and runs only during boot. There is no userspace driver and no *_grant_source for the reader itself.
    • Under boot_iso_read the kernel runs iso::boot_read_proof / iso::boot_fs_proof (called from kernel/src/main.rs) to exercise the device-read primitive and the ISO 9660 walk.
    • Under boot_iso the reader is the live boot-binary source: iso::boot_source::init (in kernel/src/main.rs run_init) builds a registry resolving each declared manifest binary name to its (lba, size) extent via open_file (name mapping through iso_dname, which applies the ISO 9660 d-character substitution xorriso records), and iso::boot_source::read_binary reads each ELF on demand. The device is owned by the registry and serialized behind a Mutex so concurrent spawns on multiple CPUs do not interleave PIO transfers on the shared IDE channel.
  • Directory/File cap fixture: the read path has no caps of its own, but the installable_image cap (kernel/src/cap/installable_image.rs) layers a read-only Directory/File CapObject over this reader for the focused QEMU install-source proof. It exposes the packaged /boot/bins/ tree to the installer smoke only; it is not a general post-bootstrap ISO filesystem service. It is granted via the qemu-gated installable_image_source (KernelCapSource::InstallableImageSource); Directory.list/ Directory.open + File.read/File.stat are served and every mutating method fails closed (read-only is structural, not a rights flag). It reuses the driver’s in-bounds checks (IsoFs::validate_extent at mount/open, AtapiDevice::read_sectors range validation per read) and is physically scoped to the ATAPI medium, so it cannot reach the writable virtio-blk target disk.
  • MMIO / Interrupt / DMA: none. Access is legacy port I/O (in/out via the module’s inb/outb/inw/outw helpers), not memory-mapped BARs. Interrupts are disabled (CTRL_NIEN) and the path is polled PIO, so there is no MSI/MSI-X vector binding. Transfers move through the data register word by word, so there is no DMA buffer and no IOMMU/bounce-buffer involvement.
  • Fail-closed / validation rules: every derived extent is validated against the volume size (IsoFs::validate_extent) before it is read, so a malformed or hostile volume cannot drive an out-of-bounds device read; directory extents are capped at MAX_DIR_BYTES and records are length/identifier-bounded before trusting them; capacity and buffer-length checks gate read_sectors; block size is floored/ceiled to MIN_BLOCK_SIZE/MAX_BLOCK_SIZE; and every status wait is SPIN_LIMIT-bounded. All failure modes funnel through IsoError (NoDevice/Timeout/DeviceError/Protocol/InvalidRequest/OutOfRange/ BufferTooSmall/ShortRead/BadVolume/NotFound/NotDirectory).
  • QEMU-emulable vs hardware-only: fully QEMU-emulable. QEMU’s -cdrom attaches an ATAPI CD-ROM on the secondary legacy IDE channel. make run-boot-iso-read proves the bounded ATAPI PIO read primitive and the ISO 9660 walk; make run-boot-iso and the default make run-smoke prove the live on-demand boot-binary load path; and make run-installable-image-source proves the read-only Directory/File install-source fixture layered over the reader. No hardware-only path.
  • kernel/src/iso/mod.rs — the ATAPI PIO reader, the ISO 9660 IsoFs driver, the boot_iso boot_source registry, and the boot-time proofs.
  • kernel/src/cap/installable_image.rs — the read-only Directory/File cap surface layered over this reader.
  • kernel/src/main.rsrun_init ISO boot-binary registry build and on-demand ELF load under boot_iso.