int int13_retry(const com32sys_t *inreg, com32sys_t *outreg) { int retry = 6; /* Number of retries */ com32sys_t tmpregs; memset(&tmpregs, 0, sizeof(tmpregs)); if ( !outreg ) outreg = &tmpregs; while ( retry-- ) { __intcall(0x13, inreg, outreg); if ( !(outreg->eflags.l & EFLAGS_CF) ) { return 0; /* CF=0, OK */ } } return -1; /* Error */ } int syslinux_read_disk(diskinfo* disk_info, void *buf, uint32_t sector, uint16_t count) { com32sys_t inreg; int status; void* bounce_buf; if (!count) { return 0; } memset(&inreg, 0, sizeof inreg); if ( disk_info->ebios ) { ebios_dapa *dapa = (struct ebios_dapa*)__com32.cs_bounce; bounce_buf = (char*)__com32.cs_bounce + SECTOR_SIZE; dapa->len = sizeof(*dapa); dapa->count = count; dapa->off = OFFS(bounce_buf); dapa->seg = SEG(bounce_buf); dapa->lba = sector; inreg.esi.w[0] = OFFS(dapa); inreg.ds = SEG(dapa); inreg.edx.b[0] = disk_info->disk; inreg.eax.b[1] = 0x42; /* Extended read */ } else { unsigned int c, h, s, t; bounce_buf = __com32.cs_bounce; if ( !disk_info->cbios ) { /* We failed to get the geometry */ if ( sector ) return -1; /* Can only read MBR */ s = 1; h = 0; c = 0; } else { s = (sector % disk_info->sect) + 1; t = sector / disk_info->sect; /* Track = head*cyl */ h = t % disk_info->head; c = t / disk_info->head; } if ( s > 63 || h > 256 || c > 1023 ) return -1; inreg.eax.b[1] = 0x02; /* Read sector(s) into memory */ inreg.eax.b[0] = count; inreg.ecx.b[1] = c & 0xff; inreg.ecx.b[0] = s + (c >> 6); inreg.edx.b[1] = h; inreg.edx.b[0] = disk_info->disk; inreg.ebx.w[0] = OFFS(bounce_buf); inreg.es = SEG(bounce_buf); } status = int13_retry(&inreg, NULL); if (status == 0) { memcpy(buf, bounce_buf, count*SECTOR_SIZE); } return status; }