iPXE
int13.c File Reference

INT 13 emulation. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <byteswap.h>
#include <errno.h>
#include <assert.h>
#include <ipxe/blockdev.h>
#include <ipxe/acpi.h>
#include <ipxe/sanboot.h>
#include <ipxe/device.h>
#include <ipxe/pci.h>
#include <ipxe/eltorito.h>
#include <ipxe/memmap.h>
#include <realmode.h>
#include <bios.h>
#include <biosint.h>
#include <bootsector.h>
#include <int13.h>

Go to the source code of this file.

Data Structures

struct  int13_data
 INT 13 SAN device private data. More...

Macros

#define int13_vector   __use_text16 ( int13_vector )
#define int13_fdd_params   __use_data16 ( int13_fdd_params )
#define num_fdds   __use_text16 ( num_fdds )
#define num_drives   __use_text16 ( num_drives )
#define eltorito_cmd   __use_data16 ( eltorito_cmd )
#define eltorito_address   __use_data16 ( eltorito_address )
#define XBFTAB_SIZE   768
 Maximum size of boot firmware table(s)
#define XBFTAB_ALIGN   16
 Alignment of boot firmware table entries.
#define xbftab   __use_data16 ( xbftab )

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static struct segoff __text16 (int13_vector)
 Vector for chaining to other INT 13 handlers.
void int13_wrapper (void)
 Assembly wrapper.
static struct int13_fdd_parameters __data16 (int13_fdd_params)
 Dummy floppy disk parameter table.
static uint8_t __text16 (num_fdds)
 Number of BIOS floppy disk drives.
static uint8_t __text16 (num_drives)
 Number of BIOS hard disk drives.
static uint32_t int13_capacity32 (struct san_device *sandev)
 Calculate SAN device capacity (limited to 32 bits)
static int int13_is_fdd (struct san_device *sandev)
 Test if SAN device is a floppy disk drive.
static int int13_parse_eltorito (struct san_device *sandev, void *scratch)
 Parse El Torito parameters.
static int int13_guess_geometry_hdd (struct san_device *sandev, void *scratch, unsigned int *heads, unsigned int *sectors)
 Guess INT 13 hard disk drive geometry.
static int int13_guess_geometry_fdd (struct san_device *sandev, unsigned int *heads, unsigned int *sectors)
 Guess INT 13 floppy disk drive geometry.
static int int13_guess_geometry (struct san_device *sandev, void *scratch)
 Guess INT 13 drive geometry.
static void int13_sync_num_drives (void)
 Update BIOS drive count.
static void int13_check_num_drives (void)
 Check number of drives.
static int int13_reset (struct san_device *sandev, struct i386_all_regs *ix86 __unused)
 INT 13, 00 - Reset disk system.
static int int13_get_last_status (struct san_device *sandev, struct i386_all_regs *ix86 __unused)
 INT 13, 01 - Get status of last operation.
static int int13_rw_sectors (struct san_device *sandev, struct i386_all_regs *ix86, int(*sandev_rw)(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer))
 Read / write sectors.
static int int13_read_sectors (struct san_device *sandev, struct i386_all_regs *ix86)
 INT 13, 02 - Read sectors.
static int int13_write_sectors (struct san_device *sandev, struct i386_all_regs *ix86)
 INT 13, 03 - Write sectors.
static int int13_get_parameters (struct san_device *sandev, struct i386_all_regs *ix86)
 INT 13, 08 - Get drive parameters.
static int int13_get_disk_type (struct san_device *sandev, struct i386_all_regs *ix86)
 INT 13, 15 - Get disk type.
static int int13_extension_check (struct san_device *sandev, struct i386_all_regs *ix86)
 INT 13, 41 - Extensions installation check.
static int int13_extended_rw (struct san_device *sandev, struct i386_all_regs *ix86, int(*sandev_rw)(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer))
 Extended read / write.
static int int13_extended_read (struct san_device *sandev, struct i386_all_regs *ix86)
 INT 13, 42 - Extended read.
static int int13_extended_write (struct san_device *sandev, struct i386_all_regs *ix86)
 INT 13, 43 - Extended write.
static int int13_extended_verify (struct san_device *sandev, struct i386_all_regs *ix86)
 INT 13, 44 - Verify sectors.
static int int13_extended_seek (struct san_device *sandev, struct i386_all_regs *ix86)
 INT 13, 44 - Extended seek.
static int int13_device_path_info (struct san_device *sandev, struct edd_device_path_information *dpi)
 Build device path information.
static int int13_get_extended_parameters (struct san_device *sandev, struct i386_all_regs *ix86)
 INT 13, 48 - Get extended parameters.
static int int13_cdrom_status_terminate (struct san_device *sandev, struct i386_all_regs *ix86)
 INT 13, 4b - Get status or terminate CD-ROM emulation.
static int int13_cdrom_read_boot_catalog (struct san_device *sandev, struct i386_all_regs *ix86)
 INT 13, 4d - Read CD-ROM boot catalog.
static __asmcall __used void int13 (struct i386_all_regs *ix86)
 INT 13 handler.
static void int13_hook_vector (void)
 Hook INT 13 handler.
static void int13_unhook_vector (void)
 Unhook INT 13 handler.
static int int13_hook (unsigned int drive, struct uri **uris, unsigned int count, unsigned int flags)
 Hook INT 13 SAN device.
static void int13_unhook (unsigned int drive)
 Unhook INT 13 SAN device.
static int int13_load_mbr (unsigned int drive, struct segoff *address)
 Load and verify master boot record from INT 13 drive.
static struct int13_cdrom_boot_catalog_command __data16 (eltorito_cmd)
 El Torito boot catalog command packet.
static struct int13_disk_address __bss16 (eltorito_address)
 El Torito disk address packet.
static int int13_load_eltorito (unsigned int drive, struct segoff *address)
 Load and verify El Torito boot record from INT 13 drive.
static int int13_boot (unsigned int drive, struct san_boot_config *config __unused)
 Attempt to boot from an INT 13 drive.
static uint8_t __bss16_array (xbftab, [XBFTAB_SIZE])
 The boot firmware table(s) generated by iPXE.
static int int13_install (struct acpi_header *acpi)
 Install ACPI table.
static int int13_describe (void)
 Describe SAN devices for SAN-booted operating system.
 PROVIDE_SANBOOT (pcbios, san_hook, int13_hook)
 PROVIDE_SANBOOT (pcbios, san_unhook, int13_unhook)
 PROVIDE_SANBOOT (pcbios, san_boot, int13_boot)
 PROVIDE_SANBOOT (pcbios, san_describe, int13_describe)

Variables

static uint16_t equipment_word
 Equipment word.
static const struct int13_fdd_geometry int13_fdd_geometries []
 Recognised floppy disk geometries.
static size_t xbftab_used
 Total used length of boot firmware tables.

Detailed Description

INT 13 emulation.

This module provides a mechanism for exporting block devices via the BIOS INT 13 disk interrupt interface.

Definition in file int13.c.

Macro Definition Documentation

◆ int13_vector

#define int13_vector   __use_text16 ( int13_vector )

Definition at line 102 of file int13.c.

Referenced by __text16(), int13_hook_vector(), and int13_unhook_vector().

◆ int13_fdd_params

#define int13_fdd_params   __use_data16 ( int13_fdd_params )

Definition at line 114 of file int13.c.

Referenced by __data16(), and int13_get_parameters().

◆ num_fdds

#define num_fdds   __use_text16 ( num_fdds )

Definition at line 131 of file int13.c.

Referenced by __text16(), int13_get_parameters(), int13_hook(), and int13_sync_num_drives().

◆ num_drives

#define num_drives   __use_text16 ( num_drives )

◆ eltorito_cmd

#define eltorito_cmd   __use_data16 ( eltorito_cmd )

Definition at line 1422 of file int13.c.

Referenced by __data16(), and int13_load_eltorito().

◆ eltorito_address

#define eltorito_address   __use_data16 ( eltorito_address )

Definition at line 1426 of file int13.c.

Referenced by __bss16(), and int13_load_eltorito().

◆ XBFTAB_SIZE

#define XBFTAB_SIZE   768

Maximum size of boot firmware table(s)

Definition at line 1553 of file int13.c.

Referenced by __bss16_array().

◆ XBFTAB_ALIGN

#define XBFTAB_ALIGN   16

Alignment of boot firmware table entries.

Definition at line 1556 of file int13.c.

Referenced by __bss16_array(), and int13_install().

◆ xbftab

#define xbftab   __use_data16 ( xbftab )

Definition at line 1561 of file int13.c.

Referenced by __bss16_array(), int13_describe(), and int13_install().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ __text16() [1/3]

struct segoff __text16 ( int13_vector )
static

Vector for chaining to other INT 13 handlers.

References __text16, and int13_vector.

◆ int13_wrapper()

void int13_wrapper ( void )
extern

Assembly wrapper.

Referenced by int13_hook_vector(), and int13_unhook_vector().

◆ __data16() [1/2]

struct int13_fdd_parameters __data16 ( int13_fdd_params )
static

Dummy floppy disk parameter table.

References __data16, and int13_fdd_params.

◆ __text16() [2/3]

uint8_t __text16 ( num_fdds )
static

Number of BIOS floppy disk drives.

This is derived from the equipment word. It is held in .text16 to allow for easy access by the INT 13,08 wrapper.

References num_fdds.

◆ __text16() [3/3]

uint8_t __text16 ( num_drives )
static

Number of BIOS hard disk drives.

This is a cached copy of the BIOS Data Area number of hard disk drives at 40:75. It is held in .text16 to allow for easy access by the INT 13,08 wrapper.

References num_drives.

◆ int13_capacity32()

uint32_t int13_capacity32 ( struct san_device * sandev)
inlinestatic

Calculate SAN device capacity (limited to 32 bits)

Parameters
sandevSAN device
Return values
blocksNumber of blocks

Definition at line 149 of file int13.c.

149 {
150 uint64_t capacity = sandev_capacity ( sandev );
151 return ( ( capacity <= 0xffffffffUL ) ? capacity : 0xffffffff );
152}
unsigned long long uint64_t
Definition stdint.h:13
static uint64_t sandev_capacity(struct san_device *sandev)
Calculate SAN device capacity.
Definition sanboot.h:246

References sandev_capacity().

Referenced by int13_get_disk_type(), and int13_guess_geometry().

◆ int13_is_fdd()

int int13_is_fdd ( struct san_device * sandev)
inlinestatic

Test if SAN device is a floppy disk drive.

Parameters
sandevSAN device
Return values
is_fddSAN device is a floppy disk drive

Definition at line 160 of file int13.c.

160 {
161 return ( ! ( sandev->drive & 0x80 ) );
162}
unsigned int drive
Drive number.
Definition sanboot.h:66

References san_device::drive.

Referenced by int13_extended_rw(), int13_extension_check(), int13_get_disk_type(), int13_get_parameters(), int13_guess_geometry(), and int13_sync_num_drives().

◆ int13_parse_eltorito()

int int13_parse_eltorito ( struct san_device * sandev,
void * scratch )
static

Parse El Torito parameters.

Parameters
sandevSAN device
scratchScratch area for single-sector reads
Return values
rcReturn status code

Reads and parses El Torito parameters, if present.

Definition at line 173 of file int13.c.

173 {
174 struct int13_data *int13 = sandev->priv;
175 static const struct eltorito_descriptor_fixed boot_check = {
176 .type = ISO9660_TYPE_BOOT,
177 .id = ISO9660_ID,
178 .version = 1,
179 .system_id = "EL TORITO SPECIFICATION",
180 };
181 struct eltorito_descriptor *boot = scratch;
182 int rc;
183
184 /* Read boot record volume descriptor */
185 if ( ( rc = sandev_read ( sandev, ELTORITO_LBA, 1, boot ) ) != 0 ) {
186 DBGC ( sandev->drive, "INT13 drive %02x could not read El "
187 "Torito boot record volume descriptor: %s\n",
188 sandev->drive, strerror ( rc ) );
189 return rc;
190 }
191
192 /* Check for an El Torito boot catalog */
193 if ( memcmp ( boot, &boot_check, sizeof ( boot_check ) ) == 0 ) {
194 int13->boot_catalog = boot->sector;
195 DBGC ( sandev->drive, "INT13 drive %02x has an El Torito boot "
196 "catalog at LBA %08x\n", sandev->drive,
197 int13->boot_catalog );
198 } else {
199 DBGC ( sandev->drive, "INT13 drive %02x has no El Torito boot "
200 "catalog\n", sandev->drive );
201 }
202
203 return 0;
204}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define ELTORITO_LBA
El Torito Boot Record Volume Descriptor block address.
Definition eltorito.h:39
#define DBGC(...)
Definition compiler.h:505
static __asmcall __used void int13(struct i386_all_regs *ix86)
INT 13 handler.
Definition int13.c:1074
#define ISO9660_TYPE_BOOT
ISO9660 Boot Volume Descriptor type.
Definition iso9660.h:40
#define ISO9660_ID
ISO9660 identifier.
Definition iso9660.h:43
int sandev_read(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer)
Read from SAN device.
Definition sanboot.c:647
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
An El Torito Boot Record Volume Descriptor (fixed portion)
Definition eltorito.h:17
An El Torito Boot Record Volume Descriptor.
Definition eltorito.h:29
uint32_t sector
Boot catalog sector.
Definition eltorito.h:35
INT 13 SAN device private data.
Definition int13.c:56
void * priv
Driver private data.
Definition sanboot.h:90

References DBGC, san_device::drive, ELTORITO_LBA, int13(), ISO9660_ID, ISO9660_TYPE_BOOT, memcmp(), san_device::priv, rc, sandev_read(), eltorito_descriptor::sector, and strerror().

Referenced by int13_hook().

◆ int13_guess_geometry_hdd()

int int13_guess_geometry_hdd ( struct san_device * sandev,
void * scratch,
unsigned int * heads,
unsigned int * sectors )
static

Guess INT 13 hard disk drive geometry.

Parameters
sandevSAN device
scratchScratch area for single-sector reads
Return values
headsGuessed number of heads
sectorsGuessed number of sectors per track
rcReturn status code

Guesses the drive geometry by inspecting the partition table.

Definition at line 217 of file int13.c.

219 {
220 struct master_boot_record *mbr = scratch;
221 struct partition_table_entry *partition;
222 unsigned int i;
223 unsigned int start_cylinder;
224 unsigned int start_head;
225 unsigned int start_sector;
226 unsigned int end_head;
227 unsigned int end_sector;
228 int rc;
229
230 /* Read partition table */
231 if ( ( rc = sandev_read ( sandev, 0, 1, mbr ) ) != 0 ) {
232 DBGC ( sandev->drive, "INT13 drive %02x could not read "
233 "partition table to guess geometry: %s\n",
234 sandev->drive, strerror ( rc ) );
235 return rc;
236 }
237 DBGC2 ( sandev->drive, "INT13 drive %02x has MBR:\n", sandev->drive );
238 DBGC2_HDA ( sandev->drive, 0, mbr, sizeof ( *mbr ) );
239 DBGC ( sandev->drive, "INT13 drive %02x has signature %08x\n",
240 sandev->drive, mbr->signature );
241
242 /* Scan through partition table and modify guesses for
243 * heads and sectors_per_track if we find any used
244 * partitions.
245 */
246 *heads = 0;
247 *sectors = 0;
248 for ( i = 0 ; i < 4 ; i++ ) {
249
250 /* Skip empty partitions */
251 partition = &mbr->partitions[i];
252 if ( ! partition->type )
253 continue;
254
255 /* If partition starts on cylinder 0 then we can
256 * unambiguously determine the number of sectors.
257 */
258 start_cylinder = PART_CYLINDER ( partition->chs_start );
259 start_head = PART_HEAD ( partition->chs_start );
260 start_sector = PART_SECTOR ( partition->chs_start );
261 if ( ( start_cylinder == 0 ) && ( start_head != 0 ) ) {
262 *sectors = ( ( partition->start + 1 - start_sector ) /
263 start_head );
264 DBGC ( sandev->drive, "INT13 drive %02x guessing "
265 "C/H/S xx/xx/%d based on partition %d\n",
266 sandev->drive, *sectors, ( i + 1 ) );
267 }
268
269 /* If partition ends on a higher head or sector number
270 * than our current guess, then increase the guess.
271 */
272 end_head = PART_HEAD ( partition->chs_end );
273 end_sector = PART_SECTOR ( partition->chs_end );
274 if ( ( end_head + 1 ) > *heads ) {
275 *heads = ( end_head + 1 );
276 DBGC ( sandev->drive, "INT13 drive %02x guessing "
277 "C/H/S xx/%d/xx based on partition %d\n",
278 sandev->drive, *heads, ( i + 1 ) );
279 }
280 if ( end_sector > *sectors ) {
281 *sectors = end_sector;
282 DBGC ( sandev->drive, "INT13 drive %02x guessing "
283 "C/H/S xx/xx/%d based on partition %d\n",
284 sandev->drive, *sectors, ( i + 1 ) );
285 }
286 }
287
288 /* Default guess is xx/255/63 */
289 if ( ! *heads )
290 *heads = 255;
291 if ( ! *sectors )
292 *sectors = 63;
293
294 return 0;
295}
#define DBGC2(...)
Definition compiler.h:522
#define DBGC2_HDA(...)
Definition compiler.h:523
uint32_t signature
Disk signature.
Definition int13.h:282
#define PART_HEAD(chs)
Definition int13.h:257
#define PART_CYLINDER(chs)
Definition int13.h:259
#define PART_SECTOR(chs)
Definition int13.h:258
uint32_t start
Linear start address.
Definition int13.h:272
struct partition_chs chs_end
C/H/S end address.
Definition int13.h:270
uint8_t type
System indicator (partition type)
Definition int13.h:268
struct partition_chs chs_start
C/H/S start address.
Definition int13.h:266
uint64_t sectors
Total number of sectors on drive.
Definition int13.h:11
uint32_t heads
Number of heads.
Definition int13.h:7
struct partition_table_entry partitions[4]
Partition table.
Definition int13.h:286
A Master Boot Record.
Definition int13.h:278
A partition table entry within the MBR.
Definition int13.h:262

References partition_table_entry::chs_end, partition_table_entry::chs_start, DBGC, DBGC2, DBGC2_HDA, san_device::drive, heads, PART_CYLINDER, PART_HEAD, PART_SECTOR, master_boot_record::partitions, rc, sandev_read(), sectors, master_boot_record::signature, partition_table_entry::start, strerror(), and partition_table_entry::type.

Referenced by int13_guess_geometry().

◆ int13_guess_geometry_fdd()

int int13_guess_geometry_fdd ( struct san_device * sandev,
unsigned int * heads,
unsigned int * sectors )
static

Guess INT 13 floppy disk drive geometry.

Parameters
sandevSAN device
Return values
headsGuessed number of heads
sectorsGuessed number of sectors per track
rcReturn status code

Guesses the drive geometry by inspecting the disk size.

Definition at line 331 of file int13.c.

333 {
334 unsigned int blocks = sandev_capacity ( sandev );
335 const struct int13_fdd_geometry *geometry;
336 unsigned int cylinders;
337 unsigned int i;
338
339 /* Look for a match against a known geometry */
340 for ( i = 0 ; i < ( sizeof ( int13_fdd_geometries ) /
341 sizeof ( int13_fdd_geometries[0] ) ) ; i++ ) {
342 geometry = &int13_fdd_geometries[i];
343 cylinders = INT13_FDD_CYLINDERS ( geometry );
344 *heads = INT13_FDD_HEADS ( geometry );
345 *sectors = INT13_FDD_SECTORS ( geometry );
346 if ( ( cylinders * (*heads) * (*sectors) ) == blocks ) {
347 DBGC ( sandev->drive, "INT13 drive %02x guessing "
348 "C/H/S %d/%d/%d based on size %dK\n",
349 sandev->drive, cylinders, *heads, *sectors,
350 ( blocks / 2 ) );
351 return 0;
352 }
353 }
354
355 /* Otherwise, assume a partial disk image in the most common
356 * format (1440K, 80/2/18).
357 */
358 *heads = 2;
359 *sectors = 18;
360 DBGC ( sandev->drive, "INT13 drive %02x guessing C/H/S xx/%d/%d "
361 "based on size %dK\n", sandev->drive, *heads, *sectors,
362 ( blocks / 2 ) );
363 return 0;
364}
uint32_t cylinders
Number of cylinders.
Definition int13.h:5
#define INT13_FDD_HEADS(geometry)
Get floppy disk number of heads.
Definition int13.h:313
#define INT13_FDD_CYLINDERS(geometry)
Get floppy disk number of cylinders.
Definition int13.h:310
#define INT13_FDD_SECTORS(geometry)
Get floppy disk number of sectors per track.
Definition int13.h:316
static const struct int13_fdd_geometry int13_fdd_geometries[]
Recognised floppy disk geometries.
Definition int13.c:298
A floppy disk geometry.
Definition int13.h:295

References cylinders, DBGC, san_device::drive, heads, INT13_FDD_CYLINDERS, int13_fdd_geometries, INT13_FDD_HEADS, INT13_FDD_SECTORS, sandev_capacity(), and sectors.

Referenced by int13_guess_geometry().

◆ int13_guess_geometry()

int int13_guess_geometry ( struct san_device * sandev,
void * scratch )
static

Guess INT 13 drive geometry.

Parameters
sandevSAN device
scratchScratch area for single-sector reads
Return values
rcReturn status code

Definition at line 373 of file int13.c.

373 {
374 struct int13_data *int13 = sandev->priv;
375 unsigned int guessed_heads;
376 unsigned int guessed_sectors;
377 unsigned int blocks;
378 unsigned int blocks_per_cyl;
379 int rc;
380
381 /* Guess geometry according to drive type */
382 if ( int13_is_fdd ( sandev ) ) {
383 if ( ( rc = int13_guess_geometry_fdd ( sandev, &guessed_heads,
384 &guessed_sectors )) != 0)
385 return rc;
386 } else {
387 if ( ( rc = int13_guess_geometry_hdd ( sandev, scratch,
388 &guessed_heads,
389 &guessed_sectors )) != 0)
390 return rc;
391 }
392
393 /* Apply guesses if no geometry already specified */
394 if ( ! int13->heads )
395 int13->heads = guessed_heads;
396 if ( ! int13->sectors_per_track )
397 int13->sectors_per_track = guessed_sectors;
398 if ( ! int13->cylinders ) {
399 /* Avoid attempting a 64-bit divide on a 32-bit system */
400 blocks = int13_capacity32 ( sandev );
401 blocks_per_cyl = ( int13->heads * int13->sectors_per_track );
402 assert ( blocks_per_cyl != 0 );
403 int13->cylinders = ( blocks / blocks_per_cyl );
404 if ( int13->cylinders > 1024 )
405 int13->cylinders = 1024;
406 }
407
408 return 0;
409}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
static int int13_is_fdd(struct san_device *sandev)
Test if SAN device is a floppy disk drive.
Definition int13.c:160
static int int13_guess_geometry_fdd(struct san_device *sandev, unsigned int *heads, unsigned int *sectors)
Guess INT 13 floppy disk drive geometry.
Definition int13.c:331
static int int13_guess_geometry_hdd(struct san_device *sandev, void *scratch, unsigned int *heads, unsigned int *sectors)
Guess INT 13 hard disk drive geometry.
Definition int13.c:217
static uint32_t int13_capacity32(struct san_device *sandev)
Calculate SAN device capacity (limited to 32 bits)
Definition int13.c:149

References assert, int13(), int13_capacity32(), int13_guess_geometry_fdd(), int13_guess_geometry_hdd(), int13_is_fdd(), san_device::priv, and rc.

Referenced by int13_hook().

◆ int13_sync_num_drives()

void int13_sync_num_drives ( void )
static

Update BIOS drive count.

Definition at line 414 of file int13.c.

414 {
415 struct san_device *sandev;
416 struct int13_data *int13;
417 uint8_t *counter;
418 uint8_t max_drive;
419 uint8_t required;
420
421 /* Get current drive counts */
424 num_fdds = ( ( equipment_word & 0x0001 ) ?
425 ( ( ( equipment_word >> 6 ) & 0x3 ) + 1 ) : 0 );
426
427 /* Ensure count is large enough to cover all of our SAN devices */
428 for_each_sandev ( sandev ) {
429 int13 = sandev->priv;
430 counter = ( int13_is_fdd ( sandev ) ? &num_fdds : &num_drives );
431 max_drive = sandev->drive;
432 if ( max_drive < int13->natural_drive )
433 max_drive = int13->natural_drive;
434 required = ( ( max_drive & 0x7f ) + 1 );
435 if ( *counter < required ) {
436 *counter = required;
437 DBGC ( sandev->drive, "INT13 drive %02x added to "
438 "drive count: %d HDDs, %d FDDs\n",
439 sandev->drive, num_drives, num_fdds );
440 }
441 }
442
443 /* Update current drive count */
444 equipment_word &= ~( ( 0x3 << 6 ) | 0x0001 );
445 if ( num_fdds ) {
446 equipment_word |= ( 0x0001 |
447 ( ( ( num_fdds - 1 ) & 0x3 ) << 6 ) );
448 }
451}
unsigned char uint8_t
Definition stdint.h:10
#define BDA_SEG
Definition bios.h:6
#define BDA_EQUIPMENT_WORD
Definition bios.h:8
#define BDA_NUM_DRIVES
Definition bios.h:19
#define for_each_sandev(sandev)
Iterate over all SAN devices.
Definition sanboot.h:197
#define num_drives
Definition int13.c:141
static uint16_t equipment_word
Equipment word.
Definition int13.c:122
#define num_fdds
Definition int13.c:131
#define put_real
Definition libkir.h:150
#define get_real
Definition libkir.h:151
unsigned int natural_drive
BIOS natural drive number (0x00-0xff)
Definition int13.c:67
A SAN device.
Definition sanboot.h:59

References BDA_EQUIPMENT_WORD, BDA_NUM_DRIVES, BDA_SEG, DBGC, san_device::drive, equipment_word, for_each_sandev, get_real, int13(), int13_is_fdd(), int13_data::natural_drive, num_drives, num_fdds, san_device::priv, and put_real.

Referenced by int13_check_num_drives(), and int13_hook().

◆ int13_check_num_drives()

void int13_check_num_drives ( void )
static

Check number of drives.

Definition at line 456 of file int13.c.

456 {
457 uint16_t check_equipment_word;
458 uint8_t check_num_drives;
459
460 get_real ( check_equipment_word, BDA_SEG, BDA_EQUIPMENT_WORD );
461 get_real ( check_num_drives, BDA_SEG, BDA_NUM_DRIVES );
462 if ( ( check_equipment_word != equipment_word ) ||
463 ( check_num_drives != num_drives ) ) {
465 }
466}
unsigned short uint16_t
Definition stdint.h:11
static void int13_sync_num_drives(void)
Update BIOS drive count.
Definition int13.c:414

References BDA_EQUIPMENT_WORD, BDA_NUM_DRIVES, BDA_SEG, equipment_word, get_real, int13_sync_num_drives(), and num_drives.

Referenced by int13().

◆ int13_reset()

int int13_reset ( struct san_device * sandev,
struct i386_all_regs *ix86 __unused )
static

INT 13, 00 - Reset disk system.

Parameters
sandevSAN device
Return values
statusStatus code

Definition at line 474 of file int13.c.

475 {
476 int rc;
477
478 DBGC2 ( sandev->drive, "Reset drive\n" );
479
480 /* Reset SAN device */
481 if ( ( rc = sandev_reset ( sandev ) ) != 0 )
483
484 return 0;
485}
#define INT13_STATUS_RESET_FAILED
Reset failed.
Definition int13.h:65
int sandev_reset(struct san_device *sandev)
Reset SAN device.
Definition sanboot.c:576

References __unused, DBGC2, san_device::drive, INT13_STATUS_RESET_FAILED, rc, and sandev_reset().

Referenced by int13().

◆ int13_get_last_status()

int int13_get_last_status ( struct san_device * sandev,
struct i386_all_regs *ix86 __unused )
static

INT 13, 01 - Get status of last operation.

Parameters
sandevSAN device
Return values
statusStatus code

Definition at line 493 of file int13.c.

494 {
495 struct int13_data *int13 = sandev->priv;
496
497 DBGC2 ( sandev->drive, "Get status of last operation\n" );
498 return int13->last_status;
499}

References __unused, DBGC2, san_device::drive, int13(), and san_device::priv.

Referenced by int13().

◆ int13_rw_sectors()

int int13_rw_sectors ( struct san_device * sandev,
struct i386_all_regs * ix86,
int(* sandev_rw )(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer) )
static

Read / write sectors.

Parameters
sandevSAN device
alNumber of sectors to read or write (must be nonzero)
chLow bits of cylinder number
cl(bits 7:6) High bits of cylinder number
cl(bits 5:0) Sector number
dhHead number
es:bxData buffer
sandev_rwSAN device read/write method
Return values
statusStatus code
alNumber of sectors read or written

Definition at line 515 of file int13.c.

520 {
521 struct int13_data *int13 = sandev->priv;
522 unsigned int cylinder, head, sector;
523 unsigned long lba;
524 unsigned int count;
525 void *buffer;
526 int rc;
527
528 /* Validate blocksize */
529 if ( sandev_blksize ( sandev ) != INT13_BLKSIZE ) {
530 DBGC ( sandev->drive, "\nINT 13 drive %02x invalid blocksize "
531 "(%zd) for non-extended read/write\n",
532 sandev->drive, sandev_blksize ( sandev ) );
533 return -INT13_STATUS_INVALID;
534 }
535
536 /* Calculate parameters */
537 cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 2 ) | ix86->regs.ch );
538 head = ix86->regs.dh;
539 sector = ( ix86->regs.cl & 0x3f );
540 if ( ( cylinder >= int13->cylinders ) ||
541 ( head >= int13->heads ) ||
542 ( sector < 1 ) || ( sector > int13->sectors_per_track ) ) {
543 DBGC ( sandev->drive, "C/H/S %d/%d/%d out of range for "
544 "geometry %d/%d/%d\n", cylinder, head, sector,
545 int13->cylinders, int13->heads,
546 int13->sectors_per_track );
547 return -INT13_STATUS_INVALID;
548 }
549 lba = ( ( ( ( cylinder * int13->heads ) + head )
550 * int13->sectors_per_track ) + sector - 1 );
551 count = ix86->regs.al;
552 buffer = real_to_virt ( ix86->segs.es, ix86->regs.bx );
553
554 DBGC2 ( sandev->drive, "C/H/S %d/%d/%d = LBA %08lx <-> %04x:%04x "
555 "(count %d)\n", cylinder, head, sector, lba, ix86->segs.es,
556 ix86->regs.bx, count );
557
558 /* Read from / write to block device */
559 if ( ( rc = sandev_rw ( sandev, lba, count, buffer ) ) != 0 ){
560 DBGC ( sandev->drive, "INT13 drive %02x I/O failed: %s\n",
561 sandev->drive, strerror ( rc ) );
563 }
564
565 return 0;
566}
uint32_t sector
Boot catalog sector.
Definition eltorito.h:5
static unsigned int count
Number of entries.
Definition dwmac.h:220
uint8_t head
Head number.
Definition int13.h:23
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition netvsc.h:5
uint64_t lba
Starting block number.
Definition int13.h:11
#define INT13_STATUS_READ_ERROR
Read error.
Definition int13.h:63
#define INT13_STATUS_INVALID
Invalid function or parameter.
Definition int13.h:61
static size_t sandev_blksize(struct san_device *sandev)
Calculate SAN device block size.
Definition sanboot.h:236
#define INT13_BLKSIZE
Block size for non-extended INT 13 calls.
Definition int13.h:72
static __always_inline void * real_to_virt(unsigned int segment, unsigned int offset)
Convert segment:offset address to virtual address.
Definition realmode.h:77
static int sandev_rw(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer, int(*block_rw)(struct interface *control, struct interface *data, uint64_t lba, unsigned int count, void *buffer, size_t len))
Read from or write to SAN device.
Definition sanboot.c:598
struct i386_seg_regs segs
Definition registers.h:175
struct i386_regs regs
Definition registers.h:176
uint16_t bx
Definition registers.h:84
uint8_t cl
Definition registers.h:97
uint8_t ch
Definition registers.h:98
uint8_t al
Definition registers.h:105
uint8_t dh
Definition registers.h:90
uint16_t es
Definition registers.h:142

References i386_regs::al, buffer, i386_regs::bx, i386_regs::ch, i386_regs::cl, count, DBGC, DBGC2, i386_regs::dh, san_device::drive, i386_seg_regs::es, head, int13(), INT13_BLKSIZE, INT13_STATUS_INVALID, INT13_STATUS_READ_ERROR, lba, san_device::priv, rc, real_to_virt(), i386_all_regs::regs, sandev_blksize(), sandev_rw(), sector, i386_all_regs::segs, and strerror().

Referenced by int13_read_sectors(), and int13_write_sectors().

◆ int13_read_sectors()

int int13_read_sectors ( struct san_device * sandev,
struct i386_all_regs * ix86 )
static

INT 13, 02 - Read sectors.

Parameters
sandevSAN device
alNumber of sectors to read (must be nonzero)
chLow bits of cylinder number
cl(bits 7:6) High bits of cylinder number
cl(bits 5:0) Sector number
dhHead number
es:bxData buffer
Return values
statusStatus code
alNumber of sectors read

Definition at line 581 of file int13.c.

582 {
583
584 DBGC2 ( sandev->drive, "Read: " );
585 return int13_rw_sectors ( sandev, ix86, sandev_read );
586}
static int int13_rw_sectors(struct san_device *sandev, struct i386_all_regs *ix86, int(*sandev_rw)(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer))
Read / write sectors.
Definition int13.c:515

References DBGC2, san_device::drive, int13_rw_sectors(), and sandev_read().

Referenced by int13().

◆ int13_write_sectors()

int int13_write_sectors ( struct san_device * sandev,
struct i386_all_regs * ix86 )
static

INT 13, 03 - Write sectors.

Parameters
sandevSAN device
alNumber of sectors to write (must be nonzero)
chLow bits of cylinder number
cl(bits 7:6) High bits of cylinder number
cl(bits 5:0) Sector number
dhHead number
es:bxData buffer
Return values
statusStatus code
alNumber of sectors written

Definition at line 601 of file int13.c.

602 {
603
604 DBGC2 ( sandev->drive, "Write: " );
605 return int13_rw_sectors ( sandev, ix86, sandev_write );
606}
int sandev_write(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer)
Write to SAN device.
Definition sanboot.c:668

References DBGC2, san_device::drive, int13_rw_sectors(), and sandev_write().

Referenced by int13().

◆ int13_get_parameters()

int int13_get_parameters ( struct san_device * sandev,
struct i386_all_regs * ix86 )
static

INT 13, 08 - Get drive parameters.

Parameters
sandevSAN device
Return values
statusStatus code
chLow bits of maximum cylinder number
cl(bits 7:6) High bits of maximum cylinder number
cl(bits 5:0) Maximum sector number
dhMaximum head number
dlNumber of drives

Definition at line 619 of file int13.c.

620 {
621 struct int13_data *int13 = sandev->priv;
622 unsigned int max_cylinder = int13->cylinders - 1;
623 unsigned int max_head = int13->heads - 1;
624 unsigned int max_sector = int13->sectors_per_track; /* sic */
625
626 DBGC2 ( sandev->drive, "Get drive parameters\n" );
627
628 /* Validate blocksize */
629 if ( sandev_blksize ( sandev ) != INT13_BLKSIZE ) {
630 DBGC ( sandev->drive, "\nINT 13 drive %02x invalid blocksize "
631 "(%zd) for non-extended parameters\n",
632 sandev->drive, sandev_blksize ( sandev ) );
633 return -INT13_STATUS_INVALID;
634 }
635
636 /* Common parameters */
637 ix86->regs.ch = ( max_cylinder & 0xff );
638 ix86->regs.cl = ( ( ( max_cylinder >> 8 ) << 6 ) | max_sector );
639 ix86->regs.dh = max_head;
640 ix86->regs.dl = ( int13_is_fdd ( sandev ) ? num_fdds : num_drives );
641
642 /* Floppy-specific parameters */
643 if ( int13_is_fdd ( sandev ) ) {
645 ix86->segs.es = rm_ds;
647 }
648
649 return 0;
650}
#define INT13_FDD_TYPE_1M44
1.44M
Definition int13.h:85
#define int13_fdd_params
Definition int13.c:114
#define rm_ds
Definition libkir.h:39
#define __from_data16(pointer)
Definition libkir.h:22
uint8_t bl
Definition registers.h:81
uint16_t di
Definition registers.h:64
uint8_t dl
Definition registers.h:89

References __from_data16, i386_regs::bl, i386_regs::ch, i386_regs::cl, DBGC, DBGC2, i386_regs::dh, i386_regs::di, i386_regs::dl, san_device::drive, i386_seg_regs::es, int13(), INT13_BLKSIZE, int13_fdd_params, INT13_FDD_TYPE_1M44, int13_is_fdd(), INT13_STATUS_INVALID, num_drives, num_fdds, san_device::priv, i386_all_regs::regs, rm_ds, sandev_blksize(), and i386_all_regs::segs.

Referenced by int13().

◆ int13_get_disk_type()

int int13_get_disk_type ( struct san_device * sandev,
struct i386_all_regs * ix86 )
static

INT 13, 15 - Get disk type.

Parameters
sandevSAN device
Return values
ahType code
cx:dxSector count
statusStatus code / disk type

Definition at line 660 of file int13.c.

661 {
662 uint32_t blocks;
663
664 DBGC2 ( sandev->drive, "Get disk type\n" );
665
666 if ( int13_is_fdd ( sandev ) ) {
667 return INT13_DISK_TYPE_FDD;
668 } else {
669 blocks = int13_capacity32 ( sandev );
670 ix86->regs.cx = ( blocks >> 16 );
671 ix86->regs.dx = ( blocks & 0xffff );
672 return INT13_DISK_TYPE_HDD;
673 }
674}
unsigned int uint32_t
Definition stdint.h:12
#define INT13_DISK_TYPE_FDD
Floppy without change-line support.
Definition int13.h:139
#define INT13_DISK_TYPE_HDD
Hard disk.
Definition int13.h:143
uint16_t cx
Definition registers.h:100
uint16_t dx
Definition registers.h:92

References i386_regs::cx, DBGC2, san_device::drive, i386_regs::dx, int13_capacity32(), INT13_DISK_TYPE_FDD, INT13_DISK_TYPE_HDD, int13_is_fdd(), and i386_all_regs::regs.

Referenced by int13().

◆ int13_extension_check()

int int13_extension_check ( struct san_device * sandev,
struct i386_all_regs * ix86 )
static

INT 13, 41 - Extensions installation check.

Parameters
sandevSAN device
bx0x55aa
Return values
bx0xaa55
cxExtensions API support bitmap
statusStatus code / API version

Definition at line 685 of file int13.c.

686 {
687
688 if ( ( ix86->regs.bx == 0x55aa ) && ! int13_is_fdd ( sandev ) ) {
689 DBGC2 ( sandev->drive, "INT13 extensions check\n" );
690 ix86->regs.bx = 0xaa55;
691 ix86->regs.cx = ( INT13_EXTENSION_LINEAR |
695 } else {
696 return -INT13_STATUS_INVALID;
697 }
698}
#define INT13_EXTENSION_64BIT
64-bit extensions are present
Definition int13.h:181
#define INT13_EXTENSION_LINEAR
Extended disk access functions supported.
Definition int13.h:175
#define INT13_EXTENSION_EDD
EDD functions supported.
Definition int13.h:179
#define INT13_EXTENSION_VER_3_0
INT13 extensions version 3.0 (EDD-3.0)
Definition int13.h:197

References i386_regs::bx, i386_regs::cx, DBGC2, san_device::drive, INT13_EXTENSION_64BIT, INT13_EXTENSION_EDD, INT13_EXTENSION_LINEAR, INT13_EXTENSION_VER_3_0, int13_is_fdd(), INT13_STATUS_INVALID, and i386_all_regs::regs.

Referenced by int13().

◆ int13_extended_rw()

int int13_extended_rw ( struct san_device * sandev,
struct i386_all_regs * ix86,
int(* sandev_rw )(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer) )
static

Extended read / write.

Parameters
sandevSAN device
ds:siDisk address packet
sandev_rwSAN device read/write method
Return values
statusStatus code

Definition at line 708 of file int13.c.

713 {
717 unsigned long count;
718 void *buffer;
719 int rc;
720
721 /* Extended reads are not allowed on floppy drives.
722 * ELTORITO.SYS seems to assume that we are really a CD-ROM if
723 * we support extended reads for a floppy drive.
724 */
725 if ( int13_is_fdd ( sandev ) )
726 return -INT13_STATUS_INVALID;
727
728 /* Get buffer size */
729 get_real ( bufsize, ix86->segs.ds,
730 ( ix86->regs.si + offsetof ( typeof ( addr ), bufsize ) ) );
731 if ( bufsize < offsetof ( typeof ( addr ), buffer_phys ) ) {
732 DBGC2 ( sandev->drive, "<invalid buffer size %#02x\n>\n",
733 bufsize );
734 return -INT13_STATUS_INVALID;
735 }
736
737 /* Read parameters from disk address structure */
738 memset ( &addr, 0, sizeof ( addr ) );
739 copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si, bufsize );
740 lba = addr.lba;
741 DBGC2 ( sandev->drive, "LBA %08llx <-> ",
742 ( ( unsigned long long ) lba ) );
743 if ( ( addr.count == 0xff ) ||
744 ( ( addr.buffer.segment == 0xffff ) &&
745 ( addr.buffer.offset == 0xffff ) ) ) {
746 buffer = phys_to_virt ( addr.buffer_phys );
747 DBGC2 ( sandev->drive, "%08llx",
748 ( ( unsigned long long ) addr.buffer_phys ) );
749 } else {
750 buffer = real_to_virt ( addr.buffer.segment,
751 addr.buffer.offset );
752 DBGC2 ( sandev->drive, "%04x:%04x", addr.buffer.segment,
753 addr.buffer.offset );
754 }
755 if ( addr.count <= 0x7f ) {
756 count = addr.count;
757 } else if ( addr.count == 0xff ) {
758 count = addr.long_count;
759 } else {
760 DBGC2 ( sandev->drive, " <invalid count %#02x>\n", addr.count );
761 return -INT13_STATUS_INVALID;
762 }
763 DBGC2 ( sandev->drive, " (count %ld)\n", count );
764
765 /* Read from / write to block device */
766 if ( ( rc = sandev_rw ( sandev, lba, count, buffer ) ) != 0 ) {
767 DBGC ( sandev->drive, "INT13 drive %02x extended I/O failed: "
768 "%s\n", sandev->drive, strerror ( rc ) );
769 /* Record that no blocks were transferred successfully */
770 addr.count = 0;
771 put_real ( addr.count, ix86->segs.ds,
772 ( ix86->regs.si +
773 offsetof ( typeof ( addr ), count ) ) );
775 }
776
777 return 0;
778}
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
uint32_t addr
Buffer address.
Definition dwmac.h:9
uint8_t bufsize
Size of the packet, in bytes.
Definition int13.h:1
uint64_t buffer_phys
Data buffer (EDD 3.0+ only)
Definition int13.h:13
void * memset(void *dest, int character, size_t len) __nonnull
#define copy_from_real
Definition libkir.h:79
#define offsetof(type, field)
Get offset of a field within a structure.
Definition stddef.h:25
uint16_t si
Definition registers.h:68
uint16_t ds
Definition registers.h:141
An INT 13 disk address packet.
Definition int13.h:88

References addr, buffer, buffer_phys, bufsize, copy_from_real, count, DBGC, DBGC2, san_device::drive, i386_seg_regs::ds, get_real, int13_is_fdd(), INT13_STATUS_INVALID, INT13_STATUS_READ_ERROR, lba, memset(), offsetof, put_real, rc, real_to_virt(), i386_all_regs::regs, sandev_rw(), i386_all_regs::segs, i386_regs::si, strerror(), and typeof().

Referenced by int13_extended_read(), and int13_extended_write().

◆ int13_extended_read()

int int13_extended_read ( struct san_device * sandev,
struct i386_all_regs * ix86 )
static

INT 13, 42 - Extended read.

Parameters
sandevSAN device
ds:siDisk address packet
Return values
statusStatus code

Definition at line 787 of file int13.c.

788 {
789
790 DBGC2 ( sandev->drive, "Extended read: " );
791 return int13_extended_rw ( sandev, ix86, sandev_read );
792}
static int int13_extended_rw(struct san_device *sandev, struct i386_all_regs *ix86, int(*sandev_rw)(struct san_device *sandev, uint64_t lba, unsigned int count, void *buffer))
Extended read / write.
Definition int13.c:708

References DBGC2, san_device::drive, int13_extended_rw(), and sandev_read().

Referenced by int13().

◆ int13_extended_write()

int int13_extended_write ( struct san_device * sandev,
struct i386_all_regs * ix86 )
static

INT 13, 43 - Extended write.

Parameters
sandevSAN device
ds:siDisk address packet
Return values
statusStatus code

Definition at line 801 of file int13.c.

802 {
803
804 DBGC2 ( sandev->drive, "Extended write: " );
805 return int13_extended_rw ( sandev, ix86, sandev_write );
806}

References DBGC2, san_device::drive, int13_extended_rw(), and sandev_write().

Referenced by int13().

◆ int13_extended_verify()

int int13_extended_verify ( struct san_device * sandev,
struct i386_all_regs * ix86 )
static

INT 13, 44 - Verify sectors.

Parameters
sandevSAN device
ds:siDisk address packet
Return values
statusStatus code

Definition at line 815 of file int13.c.

816 {
819 unsigned long count;
820
821 /* Read parameters from disk address structure */
822 if ( DBG_EXTRA ) {
823 copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si,
824 sizeof ( addr ));
825 lba = addr.lba;
826 count = addr.count;
827 DBGC2 ( sandev->drive, "Verify: LBA %08llx (count %ld)\n",
828 ( ( unsigned long long ) lba ), count );
829 }
830
831 /* We have no mechanism for verifying sectors */
832 return -INT13_STATUS_INVALID;
833}
#define DBG_EXTRA
Definition compiler.h:319

References addr, copy_from_real, count, DBG_EXTRA, DBGC2, san_device::drive, i386_seg_regs::ds, INT13_STATUS_INVALID, lba, i386_all_regs::regs, i386_all_regs::segs, and i386_regs::si.

Referenced by int13().

◆ int13_extended_seek()

int int13_extended_seek ( struct san_device * sandev,
struct i386_all_regs * ix86 )
static

INT 13, 44 - Extended seek.

Parameters
sandevSAN device
ds:siDisk address packet
Return values
statusStatus code

Definition at line 842 of file int13.c.

843 {
846 unsigned long count;
847
848 /* Read parameters from disk address structure */
849 if ( DBG_EXTRA ) {
850 copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si,
851 sizeof ( addr ));
852 lba = addr.lba;
853 count = addr.count;
854 DBGC2 ( sandev->drive, "Seek: LBA %08llx (count %ld)\n",
855 ( ( unsigned long long ) lba ), count );
856 }
857
858 /* Ignore and return success */
859 return 0;
860}

References addr, copy_from_real, count, DBG_EXTRA, DBGC2, san_device::drive, i386_seg_regs::ds, lba, i386_all_regs::regs, i386_all_regs::segs, and i386_regs::si.

Referenced by int13().

◆ int13_device_path_info()

int int13_device_path_info ( struct san_device * sandev,
struct edd_device_path_information * dpi )
static

Build device path information.

Parameters
sandevSAN device
dpiDevice path information
Return values
rcReturn status code

Definition at line 869 of file int13.c.

870 {
871 struct san_path *sanpath;
872 struct device *device;
873 struct device_description *desc;
874 unsigned int i;
875 uint8_t sum = 0;
876 int rc;
877
878 /* Reopen block device if necessary */
879 if ( sandev_needs_reopen ( sandev ) &&
880 ( ( rc = sandev_reopen ( sandev ) ) != 0 ) )
881 return rc;
882 sanpath = sandev->active;
883 assert ( sanpath != NULL );
884
885 /* Get underlying hardware device */
886 device = identify_device ( &sanpath->block );
887 if ( ! device ) {
888 DBGC ( sandev->drive, "INT13 drive %02x cannot identify "
889 "hardware device\n", sandev->drive );
890 return -ENODEV;
891 }
892
893 /* Fill in bus type and interface path */
894 desc = &device->desc;
895 switch ( desc->bus_type ) {
896 case BUS_TYPE_PCI:
897 dpi->host_bus_type.type = EDD_BUS_TYPE_PCI;
898 dpi->interface_path.pci.bus = PCI_BUS ( desc->location );
899 dpi->interface_path.pci.slot = PCI_SLOT ( desc->location );
900 dpi->interface_path.pci.function = PCI_FUNC ( desc->location );
901 dpi->interface_path.pci.channel = 0xff; /* unused */
902 break;
903 default:
904 DBGC ( sandev->drive, "INT13 drive %02x unrecognised bus "
905 "type %d\n", sandev->drive, desc->bus_type );
906 return -ENOTSUP;
907 }
908
909 /* Get EDD block device description */
910 if ( ( rc = edd_describe ( &sanpath->block, &dpi->interface_type,
911 &dpi->device_path ) ) != 0 ) {
912 DBGC ( sandev->drive, "INT13 drive %02x cannot identify "
913 "block device: %s\n", sandev->drive, strerror ( rc ) );
914 return rc;
915 }
916
917 /* Fill in common fields and fix checksum */
919 dpi->len = sizeof ( *dpi );
920 for ( i = 0 ; i < sizeof ( *dpi ) ; i++ )
921 sum += *( ( ( uint8_t * ) dpi ) + i );
922 dpi->checksum -= sum;
923
924 return 0;
925}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
struct device * identify_device(struct interface *intf)
Identify a device behind an interface.
Definition device.c:126
#define BUS_TYPE_PCI
PCI bus type.
Definition device.h:44
int edd_describe(struct interface *intf, struct edd_interface_type *type, union edd_device_path *path)
Describe a disk device using EDD.
Definition edd.c:45
#define EDD_DEVICE_PATH_INFO_KEY
EDD device path information key.
Definition edd.h:185
#define EDD_BUS_TYPE_PCI
EDD PCI bus type.
Definition edd.h:28
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
struct edd_device_path_information dpi
Device path information.
Definition int13.h:17
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define ENODEV
No such device.
Definition errno.h:510
static int sandev_needs_reopen(struct san_device *sandev)
Check if SAN device needs to be reopened.
Definition sanboot.h:256
#define PCI_FUNC(busdevfn)
Definition pci.h:286
#define PCI_BUS(busdevfn)
Definition pci.h:284
#define PCI_SLOT(busdevfn)
Definition pci.h:285
int sandev_reopen(struct san_device *sandev)
(Re)open SAN device
Definition sanboot.c:373
A hardware device description.
Definition device.h:20
A hardware device.
Definition device.h:77
struct device_description desc
Device description.
Definition device.h:83
struct san_path * active
Current active path.
Definition sanboot.h:95
A SAN path.
Definition sanboot.h:37
struct interface block
Underlying block device interface.
Definition sanboot.h:48

References san_device::active, assert, san_path::block, BUS_TYPE_PCI, DBGC, desc, device::desc, dpi, san_device::drive, EDD_BUS_TYPE_PCI, edd_describe(), EDD_DEVICE_PATH_INFO_KEY, ENODEV, ENOTSUP, identify_device(), NULL, PCI_BUS, PCI_FUNC, PCI_SLOT, rc, sandev_needs_reopen(), sandev_reopen(), and strerror().

Referenced by int13_get_extended_parameters().

◆ int13_get_extended_parameters()

int int13_get_extended_parameters ( struct san_device * sandev,
struct i386_all_regs * ix86 )
static

INT 13, 48 - Get extended parameters.

Parameters
sandevSAN device
ds:siDrive parameter table
Return values
statusStatus code

Definition at line 934 of file int13.c.

935 {
936 struct int13_data *int13 = sandev->priv;
937 struct int13_disk_parameters params;
938 struct segoff address;
939 size_t len = sizeof ( params );
941 int rc;
942
943 /* Get buffer size */
944 get_real ( bufsize, ix86->segs.ds,
945 ( ix86->regs.si + offsetof ( typeof ( params ), bufsize )));
946
947 DBGC2 ( sandev->drive, "Get extended drive parameters to "
948 "%04x:%04x+%02x\n", ix86->segs.ds, ix86->regs.si, bufsize );
949
950 /* Build drive parameters */
951 memset ( &params, 0, sizeof ( params ) );
952 params.flags = INT13_FL_DMA_TRANSPARENT;
953 if ( ( int13->cylinders < 1024 ) &&
954 ( sandev_capacity ( sandev ) <= INT13_MAX_CHS_SECTORS ) ) {
955 params.flags |= INT13_FL_CHS_VALID;
956 }
957 params.cylinders = int13->cylinders;
958 params.heads = int13->heads;
959 params.sectors_per_track = int13->sectors_per_track;
960 params.sectors = sandev_capacity ( sandev );
961 params.sector_size = sandev_blksize ( sandev );
962 memset ( &params.dpte, 0xff, sizeof ( params.dpte ) );
963 if ( ( rc = int13_device_path_info ( sandev, &params.dpi ) ) != 0 ) {
964 DBGC ( sandev->drive, "INT13 drive %02x could not provide "
965 "device path information: %s\n",
966 sandev->drive, strerror ( rc ) );
967 len = offsetof ( typeof ( params ), dpi );
968 }
969
970 /* Calculate returned "buffer size" (which will be less than
971 * the length actually copied if device path information is
972 * present).
973 */
974 if ( bufsize < offsetof ( typeof ( params ), dpte ) )
975 return -INT13_STATUS_INVALID;
976 if ( bufsize < offsetof ( typeof ( params ), dpi ) ) {
977 params.bufsize = offsetof ( typeof ( params ), dpte );
978 } else {
979 params.bufsize = offsetof ( typeof ( params ), dpi );
980 }
981
982 DBGC ( sandev->drive, "INT 13 drive %02x described using extended "
983 "parameters:\n", sandev->drive );
984 address.segment = ix86->segs.ds;
985 address.offset = ix86->regs.si;
986 DBGC_HDA ( sandev->drive, address, &params, len );
987
988 /* Return drive parameters */
989 if ( len > bufsize )
990 len = bufsize;
991 copy_to_real ( ix86->segs.ds, ix86->regs.si, &params, len );
992
993 return 0;
994}
ring len
Length.
Definition dwmac.h:226
uint64_t address
Base address.
Definition ena.h:13
#define DBGC_HDA(...)
Definition compiler.h:506
#define INT13_MAX_CHS_SECTORS
Maximum number of sectors for which CHS geometry is allowed to be valid.
Definition int13.h:205
struct segoff dpte
Device parameter table extension.
Definition int13.h:15
#define INT13_FL_CHS_VALID
CHS information is valid.
Definition int13.h:155
#define INT13_FL_DMA_TRANSPARENT
DMA boundary errors handled transparently.
Definition int13.h:153
static int int13_device_path_info(struct san_device *sandev, struct edd_device_path_information *dpi)
Build device path information.
Definition int13.c:869
#define copy_to_real
Definition libkir.h:78
INT 13 disk parameters.
Definition int13.h:110

References address, bufsize, int13_disk_parameters::bufsize, copy_to_real, int13_disk_parameters::cylinders, DBGC, DBGC2, DBGC_HDA, dpi, int13_disk_parameters::dpi, dpte, int13_disk_parameters::dpte, san_device::drive, i386_seg_regs::ds, int13_disk_parameters::flags, get_real, int13_disk_parameters::heads, int13(), int13_device_path_info(), INT13_FL_CHS_VALID, INT13_FL_DMA_TRANSPARENT, INT13_MAX_CHS_SECTORS, INT13_STATUS_INVALID, len, memset(), offsetof, san_device::priv, rc, i386_all_regs::regs, sandev_blksize(), sandev_capacity(), int13_disk_parameters::sector_size, int13_disk_parameters::sectors, int13_disk_parameters::sectors_per_track, i386_all_regs::segs, i386_regs::si, strerror(), and typeof().

Referenced by int13().

◆ int13_cdrom_status_terminate()

int int13_cdrom_status_terminate ( struct san_device * sandev,
struct i386_all_regs * ix86 )
static

INT 13, 4b - Get status or terminate CD-ROM emulation.

Parameters
sandevSAN device
ds:siSpecification packet
Return values
statusStatus code

Definition at line 1003 of file int13.c.

1004 {
1005 struct int13_cdrom_specification specification;
1006
1007 DBGC2 ( sandev->drive, "Get CD-ROM emulation status to %04x:%04x%s\n",
1008 ix86->segs.ds, ix86->regs.si,
1009 ( ix86->regs.al ? "" : " and terminate" ) );
1010
1011 /* Fail if we are not a CD-ROM */
1012 if ( ! sandev->is_cdrom ) {
1013 DBGC ( sandev->drive, "INT13 drive %02x is not a CD-ROM\n",
1014 sandev->drive );
1015 return -INT13_STATUS_INVALID;
1016 }
1017
1018 /* Build specification packet */
1019 memset ( &specification, 0, sizeof ( specification ) );
1020 specification.size = sizeof ( specification );
1021 specification.drive = sandev->drive;
1022
1023 /* Return specification packet */
1024 copy_to_real ( ix86->segs.ds, ix86->regs.si, &specification,
1025 sizeof ( specification ) );
1026
1027 return 0;
1028}
Bootable CD-ROM specification packet.
Definition int13.h:208
int is_cdrom
Drive is a CD-ROM.
Definition sanboot.h:87

References i386_regs::al, copy_to_real, DBGC, DBGC2, int13_cdrom_specification::drive, san_device::drive, i386_seg_regs::ds, INT13_STATUS_INVALID, san_device::is_cdrom, memset(), i386_all_regs::regs, i386_all_regs::segs, i386_regs::si, and int13_cdrom_specification::size.

Referenced by int13().

◆ int13_cdrom_read_boot_catalog()

int int13_cdrom_read_boot_catalog ( struct san_device * sandev,
struct i386_all_regs * ix86 )
static

INT 13, 4d - Read CD-ROM boot catalog.

Parameters
sandevSAN device
ds:siCommand packet
Return values
statusStatus code

Definition at line 1038 of file int13.c.

1039 {
1040 struct int13_data *int13 = sandev->priv;
1042 unsigned int start;
1043 int rc;
1044
1045 /* Read parameters from command packet */
1046 copy_from_real ( &command, ix86->segs.ds, ix86->regs.si,
1047 sizeof ( command ) );
1048 DBGC2 ( sandev->drive, "Read CD-ROM boot catalog to %08x\n",
1049 command.buffer );
1050
1051 /* Fail if we have no boot catalog */
1052 if ( ! int13->boot_catalog ) {
1053 DBGC ( sandev->drive, "INT13 drive %02x has no boot catalog\n",
1054 sandev->drive );
1055 return -INT13_STATUS_INVALID;
1056 }
1057 start = ( int13->boot_catalog + command.start );
1058
1059 /* Read from boot catalog */
1060 if ( ( rc = sandev_read ( sandev, start, command.count,
1061 phys_to_virt ( command.buffer ) ) ) != 0 ) {
1062 DBGC ( sandev->drive, "INT13 drive %02x could not read boot "
1063 "catalog: %s\n", sandev->drive, strerror ( rc ) );
1065 }
1066
1067 return 0;
1068}
uint32_t start
Starting offset.
Definition netvsc.h:1
A command-line command.
Definition command.h:10
Bootable CD-ROM boot catalog command packet.
Definition int13.h:236

References copy_from_real, DBGC, DBGC2, san_device::drive, i386_seg_regs::ds, int13(), INT13_STATUS_INVALID, INT13_STATUS_READ_ERROR, san_device::priv, rc, i386_all_regs::regs, sandev_read(), i386_all_regs::segs, i386_regs::si, start, and strerror().

Referenced by int13().

◆ int13()

__asmcall __used void int13 ( struct i386_all_regs * ix86)
static

INT 13 handler.

Definition at line 1074 of file int13.c.

1074 {
1075 int command = ix86->regs.ah;
1076 unsigned int bios_drive = ix86->regs.dl;
1077 struct san_device *sandev;
1078 struct int13_data *int13;
1079 int status;
1080
1081 /* Check BIOS hasn't killed off our drive */
1083
1084 for_each_sandev ( sandev ) {
1085
1086 int13 = sandev->priv;
1087 if ( bios_drive != sandev->drive ) {
1088 /* Remap any accesses to this drive's natural number */
1089 if ( bios_drive == int13->natural_drive ) {
1090 DBGC2 ( sandev->drive, "INT13,%02x (%02x) "
1091 "remapped to (%02x)\n", ix86->regs.ah,
1092 bios_drive, sandev->drive );
1093 ix86->regs.dl = sandev->drive;
1094 return;
1095 } else if ( ( ( bios_drive & 0x7f ) == 0x7f ) &&
1097 && sandev->is_cdrom ) {
1098 /* Catch non-drive-specific CD-ROM calls */
1099 } else {
1100 continue;
1101 }
1102 }
1103
1104 DBGC2 ( sandev->drive, "INT13,%02x (%02x): ",
1105 ix86->regs.ah, bios_drive );
1106
1107 switch ( command ) {
1108 case INT13_RESET:
1109 status = int13_reset ( sandev, ix86 );
1110 break;
1112 status = int13_get_last_status ( sandev, ix86 );
1113 break;
1114 case INT13_READ_SECTORS:
1115 status = int13_read_sectors ( sandev, ix86 );
1116 break;
1118 status = int13_write_sectors ( sandev, ix86 );
1119 break;
1121 status = int13_get_parameters ( sandev, ix86 );
1122 break;
1124 status = int13_get_disk_type ( sandev, ix86 );
1125 break;
1127 status = int13_extension_check ( sandev, ix86 );
1128 break;
1130 status = int13_extended_read ( sandev, ix86 );
1131 break;
1133 status = int13_extended_write ( sandev, ix86 );
1134 break;
1136 status = int13_extended_verify ( sandev, ix86 );
1137 break;
1139 status = int13_extended_seek ( sandev, ix86 );
1140 break;
1142 status = int13_get_extended_parameters ( sandev, ix86 );
1143 break;
1145 status = int13_cdrom_status_terminate ( sandev, ix86 );
1146 break;
1148 status = int13_cdrom_read_boot_catalog ( sandev, ix86 );
1149 break;
1150 default:
1151 DBGC2 ( sandev->drive, "*** Unrecognised INT13 ***\n" );
1153 break;
1154 }
1155
1156 /* Store status for INT 13,01 */
1157 int13->last_status = status;
1158
1159 /* Negative status indicates an error */
1160 if ( status < 0 ) {
1161 status = -status;
1162 DBGC ( sandev->drive, "INT13,%02x (%02x) failed with "
1163 "status %02x\n", ix86->regs.ah, sandev->drive,
1164 status );
1165 } else {
1166 ix86->flags &= ~CF;
1167 }
1168 ix86->regs.ah = status;
1169
1170 /* Set OF to indicate to wrapper not to chain this call */
1171 ix86->flags |= OF;
1172
1173 return;
1174 }
1175}
uint8_t status
Status.
Definition ena.h:5
#define INT13_EXTENDED_VERIFY
Verify sectors.
Definition int13.h:41
#define INT13_EXTENDED_WRITE
Extended write.
Definition int13.h:39
#define INT13_CDROM_READ_BOOT_CATALOG
Read CD-ROM boot catalog.
Definition int13.h:49
#define INT13_GET_PARAMETERS
Get drive parameters.
Definition int13.h:31
#define INT13_RESET
Reset disk system.
Definition int13.h:23
#define INT13_GET_LAST_STATUS
Get status of last operation.
Definition int13.h:25
#define INT13_WRITE_SECTORS
Write sectors.
Definition int13.h:29
#define INT13_EXTENDED_READ
Extended read.
Definition int13.h:37
#define INT13_GET_DISK_TYPE
Get disk type.
Definition int13.h:33
#define INT13_READ_SECTORS
Read sectors.
Definition int13.h:27
#define INT13_CDROM_STATUS_TERMINATE
Get CD-ROM status / terminate emulation.
Definition int13.h:47
#define INT13_GET_EXTENDED_PARAMETERS
Get extended drive parameters.
Definition int13.h:45
#define INT13_EXTENSION_CHECK
Extensions installation check.
Definition int13.h:35
#define INT13_EXTENDED_SEEK
Extended seek.
Definition int13.h:43
static int int13_cdrom_read_boot_catalog(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 4d - Read CD-ROM boot catalog.
Definition int13.c:1038
static int int13_read_sectors(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 02 - Read sectors.
Definition int13.c:581
static int int13_get_parameters(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 08 - Get drive parameters.
Definition int13.c:619
static int int13_extended_write(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 43 - Extended write.
Definition int13.c:801
static int int13_reset(struct san_device *sandev, struct i386_all_regs *ix86 __unused)
INT 13, 00 - Reset disk system.
Definition int13.c:474
static int int13_extended_verify(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 44 - Verify sectors.
Definition int13.c:815
static void int13_check_num_drives(void)
Check number of drives.
Definition int13.c:456
static int int13_extended_seek(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 44 - Extended seek.
Definition int13.c:842
static int int13_extended_read(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 42 - Extended read.
Definition int13.c:787
static int int13_extension_check(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 41 - Extensions installation check.
Definition int13.c:685
static int int13_write_sectors(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 03 - Write sectors.
Definition int13.c:601
static int int13_get_extended_parameters(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 48 - Get extended parameters.
Definition int13.c:934
static int int13_get_disk_type(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 15 - Get disk type.
Definition int13.c:660
static int int13_get_last_status(struct san_device *sandev, struct i386_all_regs *ix86 __unused)
INT 13, 01 - Get status of last operation.
Definition int13.c:493
static int int13_cdrom_status_terminate(struct san_device *sandev, struct i386_all_regs *ix86)
INT 13, 4b - Get status or terminate CD-ROM emulation.
Definition int13.c:1003
#define OF
Definition registers.h:186
#define CF
Definition registers.h:181
uint32_t flags
Definition registers.h:177
uint8_t ah
Definition registers.h:106

References __asmcall, __used, i386_regs::ah, CF, DBGC, DBGC2, i386_regs::dl, san_device::drive, i386_all_regs::flags, for_each_sandev, int13(), INT13_CDROM_READ_BOOT_CATALOG, int13_cdrom_read_boot_catalog(), INT13_CDROM_STATUS_TERMINATE, int13_cdrom_status_terminate(), int13_check_num_drives(), INT13_EXTENDED_READ, int13_extended_read(), INT13_EXTENDED_SEEK, int13_extended_seek(), INT13_EXTENDED_VERIFY, int13_extended_verify(), INT13_EXTENDED_WRITE, int13_extended_write(), INT13_EXTENSION_CHECK, int13_extension_check(), INT13_GET_DISK_TYPE, int13_get_disk_type(), INT13_GET_EXTENDED_PARAMETERS, int13_get_extended_parameters(), INT13_GET_LAST_STATUS, int13_get_last_status(), INT13_GET_PARAMETERS, int13_get_parameters(), INT13_READ_SECTORS, int13_read_sectors(), INT13_RESET, int13_reset(), INT13_STATUS_INVALID, INT13_WRITE_SECTORS, int13_write_sectors(), san_device::is_cdrom, OF, san_device::priv, i386_all_regs::regs, and status.

Referenced by int13(), int13_cdrom_read_boot_catalog(), int13_get_extended_parameters(), int13_get_last_status(), int13_get_parameters(), int13_guess_geometry(), int13_hook(), int13_hook_vector(), int13_parse_eltorito(), int13_rw_sectors(), and int13_sync_num_drives().

◆ int13_hook_vector()

void int13_hook_vector ( void )
static

Hook INT 13 handler.

Definition at line 1181 of file int13.c.

1181 {
1182 /* Assembly wrapper to call int13(). int13() sets OF if we
1183 * should not chain to the previous handler. (The wrapper
1184 * clears CF and OF before calling int13()).
1185 */
1187 TEXT16_CODE ( "\nint13_wrapper:\n\t"
1188 /* Preserve %ax and %dx for future reference */
1189 "pushw %%bp\n\t"
1190 "movw %%sp, %%bp\n\t"
1191 "pushw %%ax\n\t"
1192 "pushw %%dx\n\t"
1193 /* Clear OF, set CF, call int13() */
1194 "orb $0, %%al\n\t"
1195 "stc\n\t"
1196 VIRT_CALL ( int13 )
1197 /* Chain if OF not set */
1198 "jo 1f\n\t"
1199 "pushfw\n\t"
1200 "lcall *%%cs:int13_vector\n\t"
1201 "\n1:\n\t"
1202 /* Overwrite flags for iret */
1203 "pushfw\n\t"
1204 "popw 6(%%bp)\n\t"
1205 /* Fix up %dl:
1206 *
1207 * INT 13,15 : do nothing if hard disk
1208 * INT 13,08 : load with number of drives
1209 * all others: restore original value
1210 */
1211 "cmpb $0x15, -1(%%bp)\n\t"
1212 "jne 2f\n\t"
1213 "testb $0x80, -4(%%bp)\n\t"
1214 "jnz 3f\n\t"
1215 "\n2:\n\t"
1216 "movb -4(%%bp), %%dl\n\t"
1217 "cmpb $0x08, -1(%%bp)\n\t"
1218 "jne 3f\n\t"
1219 "testb $0x80, %%dl\n\t"
1220 "movb %%cs:num_drives, %%dl\n\t"
1221 "jnz 3f\n\t"
1222 "movb %%cs:num_fdds, %%dl\n\t"
1223 /* Return */
1224 "\n3:\n\t"
1225 "movw %%bp, %%sp\n\t"
1226 "popw %%bp\n\t"
1227 "iret\n\t" ) : : );
1228
1230}
__asm__ __volatile__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
unsigned long intptr_t
Definition stdint.h:21
void hook_bios_interrupt(unsigned int interrupt, unsigned int handler, struct segoff *chain_vector)
Hook INT vector.
Definition biosint.c:25
void int13_wrapper(void)
Assembly wrapper.
#define int13_vector
Definition int13.c:102
#define TEXT16_CODE(asm_code_str)
Definition libkir.h:217
#define VIRT_CALL(function)
Call C function from real-mode code.
Definition librm.h:72
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")

References __asm__(), __volatile__(), hook_bios_interrupt(), int13(), int13_vector, int13_wrapper(), TEXT16_CODE, and VIRT_CALL.

Referenced by int13_hook().

◆ int13_unhook_vector()

void int13_unhook_vector ( void )
static

Unhook INT 13 handler.

Definition at line 1235 of file int13.c.

1235 {
1237 &int13_vector );
1238}
int unhook_bios_interrupt(unsigned int interrupt, unsigned int handler, struct segoff *chain_vector)
Unhook INT vector.
Definition biosint.c:70

References int13_vector, int13_wrapper(), and unhook_bios_interrupt().

Referenced by int13_unhook().

◆ int13_hook()

int int13_hook ( unsigned int drive,
struct uri ** uris,
unsigned int count,
unsigned int flags )
static

Hook INT 13 SAN device.

Parameters
driveDrive number
urisList of URIs
countNumber of URIs
flagsFlags
Return values
driveDrive number, or negative error

Registers the drive with the INT 13 emulation subsystem, and hooks the INT 13 interrupt vector (if not already hooked).

Definition at line 1252 of file int13.c.

1253 {
1254 struct san_device *sandev;
1255 struct int13_data *int13;
1256 unsigned int natural_drive;
1257 void *scratch;
1258 int need_hook = ( ! have_sandevs() );
1259 int rc;
1260
1261 /* Calculate natural drive number */
1263 natural_drive = ( ( drive & 0x80 ) ? ( num_drives | 0x80 ) : num_fdds );
1264
1265 /* Use natural drive number if directed to do so */
1266 if ( ( drive & 0x7f ) == 0x7f )
1268
1269 /* Allocate SAN device */
1270 sandev = alloc_sandev ( uris, count, sizeof ( *int13 ) );
1271 if ( ! sandev ) {
1272 rc = -ENOMEM;
1273 goto err_alloc;
1274 }
1275 int13 = sandev->priv;
1276 int13->natural_drive = natural_drive;
1277
1278 /* Register SAN device */
1279 if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) {
1280 DBGC ( drive, "INT13 drive %02x could not register: %s\n",
1281 drive, strerror ( rc ) );
1282 goto err_register;
1283 }
1284
1285 /* Allocate scratch area */
1286 scratch = malloc ( sandev_blksize ( sandev ) );
1287 if ( ! scratch )
1288 goto err_alloc_scratch;
1289
1290 /* Parse parameters, if present */
1291 if ( sandev->is_cdrom &&
1292 ( ( rc = int13_parse_eltorito ( sandev, scratch ) ) != 0 ) )
1293 goto err_parse_eltorito;
1294
1295 /* Give drive a default geometry, if applicable */
1296 if ( ( sandev_blksize ( sandev ) == INT13_BLKSIZE ) &&
1297 ( ( rc = int13_guess_geometry ( sandev, scratch ) ) != 0 ) )
1298 goto err_guess_geometry;
1299
1300 DBGC ( drive, "INT13 drive %02x (naturally %02x) registered with "
1301 "C/H/S geometry %d/%d/%d\n", drive, int13->natural_drive,
1302 int13->cylinders, int13->heads, int13->sectors_per_track );
1303
1304 /* Hook INT 13 vector if not already hooked */
1305 if ( need_hook ) {
1307 devices_get();
1308 }
1309
1310 /* Update BIOS drive count */
1312
1313 free ( scratch );
1314 return drive;
1315
1316 err_guess_geometry:
1317 err_parse_eltorito:
1318 free ( scratch );
1319 err_alloc_scratch:
1320 unregister_sandev ( sandev );
1321 err_register:
1322 sandev_put ( sandev );
1323 err_alloc:
1324 return rc;
1325}
static void devices_get(void)
Prevent devices from being removed on shutdown.
Definition device.h:165
uint8_t flags
Flags.
Definition ena.h:7
uint8_t drive
Drive number.
Definition int13.h:5
#define ENOMEM
Not enough space.
Definition errno.h:535
static int have_sandevs(void)
There exist some SAN devices.
Definition sanboot.h:204
static void sandev_put(struct san_device *sandev)
Drop reference to SAN device.
Definition sanboot.h:226
static int int13_parse_eltorito(struct san_device *sandev, void *scratch)
Parse El Torito parameters.
Definition int13.c:173
static void int13_hook_vector(void)
Hook INT 13 handler.
Definition int13.c:1181
static int int13_guess_geometry(struct san_device *sandev, void *scratch)
Guess INT 13 drive geometry.
Definition int13.c:373
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
int register_sandev(struct san_device *sandev, unsigned int drive, unsigned int flags)
Register SAN device.
Definition sanboot.c:880
void unregister_sandev(struct san_device *sandev)
Unregister SAN device.
Definition sanboot.c:942
struct san_device * alloc_sandev(struct uri **uris, unsigned int count, size_t priv_size)
Allocate SAN device.
Definition sanboot.c:837

References alloc_sandev(), count, DBGC, devices_get(), drive, ENOMEM, flags, free, have_sandevs(), int13(), INT13_BLKSIZE, int13_guess_geometry(), int13_hook_vector(), int13_parse_eltorito(), int13_sync_num_drives(), san_device::is_cdrom, malloc(), int13_data::natural_drive, num_drives, num_fdds, san_device::priv, rc, register_sandev(), sandev_blksize(), sandev_put(), strerror(), and unregister_sandev().

Referenced by PROVIDE_SANBOOT().

◆ int13_unhook()

void int13_unhook ( unsigned int drive)
static

Unhook INT 13 SAN device.

Parameters
driveDrive number

Unregisters the drive from the INT 13 emulation subsystem. If this is the last SAN device, the INT 13 vector is unhooked (if possible).

Definition at line 1336 of file int13.c.

1336 {
1337 struct san_device *sandev;
1338
1339 /* Find drive */
1340 sandev = sandev_find ( drive );
1341 if ( ! sandev ) {
1342 DBGC ( drive, "INT13 drive %02x is not a SAN drive\n", drive );
1343 return;
1344 }
1345
1346 /* Unregister SAN device */
1347 unregister_sandev ( sandev );
1348
1349 /* Should adjust BIOS drive count, but it's difficult
1350 * to do so reliably.
1351 */
1352
1353 DBGC ( drive, "INT13 drive %02x unregistered\n", drive );
1354
1355 /* Unhook INT 13 vector if no more drives */
1356 if ( ! have_sandevs() ) {
1357 devices_put();
1359 }
1360
1361 /* Drop reference to drive */
1362 sandev_put ( sandev );
1363}
static void devices_put(void)
Allow devices to be removed on shutdown.
Definition device.h:173
static void int13_unhook_vector(void)
Unhook INT 13 handler.
Definition int13.c:1235
struct san_device * sandev_find(unsigned int drive)
Find SAN device by drive number.
Definition sanboot.c:92

References DBGC, devices_put(), drive, have_sandevs(), int13_unhook_vector(), sandev_find(), sandev_put(), and unregister_sandev().

Referenced by PROVIDE_SANBOOT().

◆ int13_load_mbr()

int int13_load_mbr ( unsigned int drive,
struct segoff * address )
static

Load and verify master boot record from INT 13 drive.

Parameters
driveDrive number
addressBoot code address to fill in
Return values
rcReturn status code

Definition at line 1372 of file int13.c.

1372 {
1374 int discard_b, discard_c, discard_d;
1376
1377 /* Use INT 13, 02 to read the MBR */
1378 address->segment = 0;
1379 address->offset = 0x7c00;
1380 __asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t"
1381 "pushl %%ebx\n\t"
1382 "popw %%bx\n\t"
1383 "popw %%es\n\t"
1384 "stc\n\t"
1385 "sti\n\t"
1386 "int $0x13\n\t"
1387 "sti\n\t" /* BIOS bugs */
1388 "jc 1f\n\t"
1389 "xorw %%ax, %%ax\n\t"
1390 "\n1:\n\t"
1391 "popw %%es\n\t" )
1392 : "=a" ( status ), "=b" ( discard_b ),
1393 "=c" ( discard_c ), "=d" ( discard_d )
1394 : "a" ( 0x0201 ), "b" ( *address ),
1395 "c" ( 1 ), "d" ( drive ) );
1396 if ( status ) {
1397 DBGC ( drive, "INT13 drive %02x could not read MBR (status "
1398 "%04x)\n", drive, status );
1399 return -EIO;
1400 }
1401
1402 /* Check magic signature */
1403 get_real ( magic, address->segment,
1404 ( address->offset +
1405 offsetof ( struct master_boot_record, magic ) ) );
1406 if ( magic != INT13_MBR_MAGIC ) {
1407 DBGC ( drive, "INT13 drive %02x does not contain a valid MBR\n",
1408 drive );
1409 return -ENOEXEC;
1410 }
1411
1412 return 0;
1413}
long discard_c
Definition bigint.h:33
uint16_t magic
Magic signature.
Definition bzimage.h:1
#define INT13_MBR_MAGIC
MBR magic signature.
Definition int13.h:292
#define ENOEXEC
Exec format error.
Definition errno.h:520
#define EIO
Input/output error.
Definition errno.h:434
#define REAL_CODE(asm_code_str)
Definition libkir.h:226

References __asm__(), __volatile__(), address, DBGC, discard_c, drive, EIO, ENOEXEC, get_real, INT13_MBR_MAGIC, magic, offsetof, REAL_CODE, and status.

Referenced by int13_boot().

◆ __data16() [2/2]

struct int13_cdrom_boot_catalog_command __data16 ( eltorito_cmd )
static

El Torito boot catalog command packet.

References __data16, count, and eltorito_cmd.

◆ __bss16()

struct int13_disk_address __bss16 ( eltorito_address )
static

El Torito disk address packet.

References __bss16, and eltorito_address.

◆ int13_load_eltorito()

int int13_load_eltorito ( unsigned int drive,
struct segoff * address )
static

Load and verify El Torito boot record from INT 13 drive.

Parameters
driveDrive number
addressBoot code address to fill in
Return values
rcReturn status code

Definition at line 1435 of file int13.c.

1435 {
1436 struct {
1437 struct eltorito_validation_entry valid;
1438 struct eltorito_boot_entry boot;
1439 } __attribute__ (( packed )) catalog;
1441
1442 /* Use INT 13, 4d to read the boot catalog */
1443 __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
1444 "sti\n\t"
1445 "int $0x13\n\t"
1446 "sti\n\t" /* BIOS bugs */
1447 "jc 1f\n\t"
1448 "xorw %%ax, %%ax\n\t"
1449 "\n1:\n\t" )
1450 : "=a" ( status )
1451 : "a" ( 0x4d00 ), "d" ( drive ),
1452 "S" ( __from_data16 ( &eltorito_cmd ) ) );
1453 if ( status ) {
1454 DBGC ( drive, "INT13 drive %02x could not read El Torito boot "
1455 "catalog (status %04x)\n", drive, status );
1456 return -EIO;
1457 }
1458 memcpy ( &catalog, phys_to_virt ( eltorito_cmd.buffer ),
1459 sizeof ( catalog ) );
1460
1461 /* Sanity checks */
1462 if ( catalog.valid.platform_id != ELTORITO_PLATFORM_X86 ) {
1463 DBGC ( drive, "INT13 drive %02x El Torito specifies unknown "
1464 "platform %02x\n", drive, catalog.valid.platform_id );
1465 return -ENOEXEC;
1466 }
1467 if ( catalog.boot.indicator != ELTORITO_BOOTABLE ) {
1468 DBGC ( drive, "INT13 drive %02x El Torito is not bootable\n",
1469 drive );
1470 return -ENOEXEC;
1471 }
1472 if ( catalog.boot.media_type != ELTORITO_NO_EMULATION ) {
1473 DBGC ( drive, "INT13 drive %02x El Torito requires emulation "
1474 "type %02x\n", drive, catalog.boot.media_type );
1475 return -ENOTSUP;
1476 }
1477 DBGC ( drive, "INT13 drive %02x El Torito boot image at LBA %08x "
1478 "(count %d)\n", drive, catalog.boot.start, catalog.boot.length );
1479 address->segment = ( catalog.boot.load_segment ?
1480 catalog.boot.load_segment : 0x7c0 );
1481 address->offset = 0;
1482 DBGC ( drive, "INT13 drive %02x El Torito boot image loads at "
1483 "%04x:%04x\n", drive, address->segment, address->offset );
1484
1485 /* Use INT 13, 42 to read the boot image */
1486 eltorito_address.bufsize =
1488 eltorito_address.count = catalog.boot.length;
1489 eltorito_address.buffer = *address;
1490 eltorito_address.lba = catalog.boot.start;
1491 __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
1492 "sti\n\t"
1493 "int $0x13\n\t"
1494 "sti\n\t" /* BIOS bugs */
1495 "jc 1f\n\t"
1496 "xorw %%ax, %%ax\n\t"
1497 "\n1:\n\t" )
1498 : "=a" ( status )
1499 : "a" ( 0x4200 ), "d" ( drive ),
1500 "S" ( __from_data16 ( &eltorito_address ) ) );
1501 if ( status ) {
1502 DBGC ( drive, "INT13 drive %02x could not read El Torito boot "
1503 "image (status %04x)\n", drive, status );
1504 return -EIO;
1505 }
1506
1507 return 0;
1508}
@ ELTORITO_PLATFORM_X86
Definition eltorito.h:64
@ ELTORITO_NO_EMULATION
No emulation.
Definition eltorito.h:100
#define ELTORITO_BOOTABLE
Boot indicator for a bootable ISO image.
Definition eltorito.h:95
#define __attribute__(x)
Definition compiler.h:10
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define eltorito_address
Definition int13.c:1426
#define eltorito_cmd
Definition int13.c:1422
A bootable entry in the El Torito Boot Catalog.
Definition eltorito.h:70
An El Torito Boot Catalog Validation Entry.
Definition eltorito.h:42

References __asm__(), __attribute__, __from_data16, __volatile__(), address, buffer_phys, DBGC, drive, EIO, eltorito_address, ELTORITO_BOOTABLE, eltorito_cmd, ELTORITO_NO_EMULATION, ELTORITO_PLATFORM_X86, ENOEXEC, ENOTSUP, memcpy(), offsetof, REAL_CODE, status, and typeof().

Referenced by int13_boot().

◆ int13_boot()

int int13_boot ( unsigned int drive,
struct san_boot_config *config __unused )
static

Attempt to boot from an INT 13 drive.

Parameters
driveDrive number
configBoot configuration parameters
Return values
rcReturn status code

This boots from the specified INT 13 drive by loading the Master Boot Record to 0000:7c00 and jumping to it. INT 18 is hooked to capture an attempt by the MBR to boot the next device. (This is the closest thing to a return path from an MBR).

Note that this function can never return success, by definition.

Definition at line 1524 of file int13.c.

1525 {
1526 struct segoff address;
1527 int rc;
1528
1529 /* Look for a usable boot sector */
1530 if ( ( ( rc = int13_load_mbr ( drive, &address ) ) != 0 ) &&
1531 ( ( rc = int13_load_eltorito ( drive, &address ) ) != 0 ) )
1532 return rc;
1533
1534 /* Dump out memory map prior to boot, if memmap debugging is
1535 * enabled. Not required for program flow, but we have so
1536 * many problems that turn out to be memory-map related that
1537 * it's worth doing.
1538 */
1539 memmap_dump_all ( 1 );
1540
1541 /* Jump to boot sector */
1542 if ( ( rc = call_bootsector ( address.segment, address.offset,
1543 drive ) ) != 0 ) {
1544 DBGC ( drive, "INT13 drive %02x boot returned: %s\n",
1545 drive, strerror ( rc ) );
1546 return rc;
1547 }
1548
1549 return -ECANCELED; /* -EIMPOSSIBLE */
1550}
int call_bootsector(unsigned int segment, unsigned int offset, unsigned int drive)
Jump to preloaded bootsector.
Definition bootsector.c:64
#define ECANCELED
Operation canceled.
Definition errno.h:344
static void memmap_dump_all(int hide)
Dump system memory map (for debugging)
Definition memmap.h:216
static int int13_load_mbr(unsigned int drive, struct segoff *address)
Load and verify master boot record from INT 13 drive.
Definition int13.c:1372
static int int13_load_eltorito(unsigned int drive, struct segoff *address)
Load and verify El Torito boot record from INT 13 drive.
Definition int13.c:1435

References __unused, address, call_bootsector(), DBGC, drive, ECANCELED, int13_load_eltorito(), int13_load_mbr(), memmap_dump_all(), rc, and strerror().

Referenced by PROVIDE_SANBOOT().

◆ __bss16_array()

uint8_t __bss16_array ( xbftab )
static

The boot firmware table(s) generated by iPXE.

References xbftab, XBFTAB_ALIGN, and XBFTAB_SIZE.

◆ int13_install()

int int13_install ( struct acpi_header * acpi)
static

Install ACPI table.

Parameters
acpiACPI description header
Return values
rcReturn status code

Definition at line 1572 of file int13.c.

1572 {
1573 struct segoff xbft_address;
1574 struct acpi_header *installed;
1575 size_t len;
1576
1577 /* Check length */
1578 len = acpi->length;
1579 if ( len > ( sizeof ( xbftab ) - xbftab_used ) ) {
1580 DBGC ( acpi, "INT13 out of space for %s table\n",
1581 acpi_name ( acpi->signature ) );
1582 return -ENOSPC;
1583 }
1584
1585 /* Install table */
1586 installed = ( ( ( void * ) xbftab ) + xbftab_used );
1587 memcpy ( installed, acpi, len );
1588 xbft_address.segment = rm_ds;
1589 xbft_address.offset = __from_data16 ( installed );
1590
1591 /* Fill in common parameters */
1592 strncpy ( installed->oem_id, "FENSYS",
1593 sizeof ( installed->oem_id ) );
1594 strncpy ( installed->oem_table_id, "iPXE",
1595 sizeof ( installed->oem_table_id ) );
1596
1597 /* Fix checksum */
1598 acpi_fix_checksum ( installed );
1599
1600 /* Update used length */
1601 xbftab_used = ( ( xbftab_used + len + XBFTAB_ALIGN - 1 ) &
1602 ~( XBFTAB_ALIGN - 1 ) );
1603
1604 DBGC ( acpi, "INT13 installed %s:\n",
1605 acpi_name ( installed->signature ) );
1606 DBGC_HDA ( acpi, xbft_address, installed, len );
1607 return 0;
1608}
void acpi_fix_checksum(struct acpi_header *acpi)
Fix up ACPI table checksum.
Definition acpi.c:80
static EFI_ACPI_TABLE_PROTOCOL * acpi
ACPI table protocol protocol.
Definition efi_block.c:67
#define ENOSPC
No space left on device.
Definition errno.h:550
static const char * acpi_name(uint32_t signature)
Transcribe ACPI table signature (for debugging)
Definition acpi.h:207
#define xbftab
Definition int13.c:1561
static size_t xbftab_used
Total used length of boot firmware tables.
Definition int13.c:1564
#define XBFTAB_ALIGN
Alignment of boot firmware table entries.
Definition int13.c:1556
char * strncpy(char *dest, const char *src, size_t max)
Copy string.
Definition string.c:361
An ACPI description header.
Definition acpi.h:180
uint32_t signature
ACPI signature (4 ASCII characters)
Definition acpi.h:182
char oem_id[6]
OEM identification.
Definition acpi.h:190
char oem_table_id[8]
OEM table identification.
Definition acpi.h:192

References __from_data16, acpi, acpi_fix_checksum(), acpi_name(), DBGC, DBGC_HDA, ENOSPC, len, memcpy(), acpi_header::oem_id, acpi_header::oem_table_id, segoff::offset, rm_ds, segoff::segment, acpi_header::signature, strncpy(), xbftab, XBFTAB_ALIGN, and xbftab_used.

Referenced by int13_describe().

◆ int13_describe()

int int13_describe ( void )
static

Describe SAN devices for SAN-booted operating system.

Return values
rcReturn status code

Definition at line 1615 of file int13.c.

1615 {
1616 int rc;
1617
1618 /* Clear tables */
1619 memset ( &xbftab, 0, sizeof ( xbftab ) );
1620 xbftab_used = 0;
1621
1622 /* Install ACPI tables */
1623 if ( ( rc = acpi_install ( int13_install ) ) != 0 ) {
1624 DBG ( "INT13 could not install ACPI tables: %s\n",
1625 strerror ( rc ) );
1626 return rc;
1627 }
1628
1629 return 0;
1630}
int acpi_install(int(*install)(struct acpi_header *acpi))
Install ACPI tables.
Definition acpi.c:344
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
static int int13_install(struct acpi_header *acpi)
Install ACPI table.
Definition int13.c:1572

References acpi_install(), DBG, int13_install(), memset(), rc, strerror(), xbftab, and xbftab_used.

Referenced by PROVIDE_SANBOOT().

◆ PROVIDE_SANBOOT() [1/4]

PROVIDE_SANBOOT ( pcbios ,
san_hook ,
int13_hook  )

References int13_hook(), and san_hook().

◆ PROVIDE_SANBOOT() [2/4]

PROVIDE_SANBOOT ( pcbios ,
san_unhook ,
int13_unhook  )

References int13_unhook(), and san_unhook().

◆ PROVIDE_SANBOOT() [3/4]

PROVIDE_SANBOOT ( pcbios ,
san_boot ,
int13_boot  )

References int13_boot(), and san_boot().

◆ PROVIDE_SANBOOT() [4/4]

PROVIDE_SANBOOT ( pcbios ,
san_describe ,
int13_describe  )

References int13_describe(), and san_describe().

Variable Documentation

◆ equipment_word

uint16_t equipment_word
static

Equipment word.

This is a cached copy of the BIOS Data Area equipment word at 40:10.

Definition at line 122 of file int13.c.

Referenced by int13_check_num_drives(), and int13_sync_num_drives().

◆ int13_fdd_geometries

const struct int13_fdd_geometry int13_fdd_geometries[]
static
Initial value:
= {
INT13_FDD_GEOMETRY ( 40, 1, 8 ),
INT13_FDD_GEOMETRY ( 40, 1, 9 ),
INT13_FDD_GEOMETRY ( 40, 2, 8 ),
INT13_FDD_GEOMETRY ( 40, 1, 9 ),
INT13_FDD_GEOMETRY ( 80, 2, 8 ),
INT13_FDD_GEOMETRY ( 80, 2, 9 ),
INT13_FDD_GEOMETRY ( 80, 2, 15 ),
INT13_FDD_GEOMETRY ( 80, 2, 18 ),
INT13_FDD_GEOMETRY ( 80, 2, 20 ),
INT13_FDD_GEOMETRY ( 80, 2, 21 ),
INT13_FDD_GEOMETRY ( 82, 2, 21 ),
INT13_FDD_GEOMETRY ( 83, 2, 21 ),
INT13_FDD_GEOMETRY ( 80, 2, 22 ),
INT13_FDD_GEOMETRY ( 80, 2, 23 ),
INT13_FDD_GEOMETRY ( 80, 2, 24 ),
INT13_FDD_GEOMETRY ( 80, 2, 36 ),
INT13_FDD_GEOMETRY ( 80, 2, 39 ),
INT13_FDD_GEOMETRY ( 80, 2, 40 ),
INT13_FDD_GEOMETRY ( 80, 2, 44 ),
INT13_FDD_GEOMETRY ( 80, 2, 48 ),
}
#define INT13_FDD_GEOMETRY(cylinders, heads, sectors)
Define a floppy disk geometry.
Definition int13.h:303

Recognised floppy disk geometries.

Definition at line 298 of file int13.c.

298 {
299 INT13_FDD_GEOMETRY ( 40, 1, 8 ),
300 INT13_FDD_GEOMETRY ( 40, 1, 9 ),
301 INT13_FDD_GEOMETRY ( 40, 2, 8 ),
302 INT13_FDD_GEOMETRY ( 40, 1, 9 ),
303 INT13_FDD_GEOMETRY ( 80, 2, 8 ),
304 INT13_FDD_GEOMETRY ( 80, 2, 9 ),
305 INT13_FDD_GEOMETRY ( 80, 2, 15 ),
306 INT13_FDD_GEOMETRY ( 80, 2, 18 ),
307 INT13_FDD_GEOMETRY ( 80, 2, 20 ),
308 INT13_FDD_GEOMETRY ( 80, 2, 21 ),
309 INT13_FDD_GEOMETRY ( 82, 2, 21 ),
310 INT13_FDD_GEOMETRY ( 83, 2, 21 ),
311 INT13_FDD_GEOMETRY ( 80, 2, 22 ),
312 INT13_FDD_GEOMETRY ( 80, 2, 23 ),
313 INT13_FDD_GEOMETRY ( 80, 2, 24 ),
314 INT13_FDD_GEOMETRY ( 80, 2, 36 ),
315 INT13_FDD_GEOMETRY ( 80, 2, 39 ),
316 INT13_FDD_GEOMETRY ( 80, 2, 40 ),
317 INT13_FDD_GEOMETRY ( 80, 2, 44 ),
318 INT13_FDD_GEOMETRY ( 80, 2, 48 ),
319};

Referenced by int13_guess_geometry_fdd().

◆ xbftab_used

size_t xbftab_used
static

Total used length of boot firmware tables.

Definition at line 1564 of file int13.c.

Referenced by int13_describe(), and int13_install().