15b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* bios.c - implement C part of low-level BIOS disk input and output */ 25b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* 35b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * GRUB -- GRand Unified Bootloader 45b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Copyright (C) 1999,2000,2003,2004 Free Software Foundation, Inc. 55b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * 65b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * This program is free software; you can redistribute it and/or modify 75b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * it under the terms of the GNU General Public License as published by 85b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * the Free Software Foundation; either version 2 of the License, or 95b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * (at your option) any later version. 105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * 115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * This program is distributed in the hope that it will be useful, 125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of 135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * GNU General Public License for more details. 155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * 165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * You should have received a copy of the GNU General Public License 175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * along with this program; if not, write to the Free Software 185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */ 205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "shared.h" 225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* These are defined in asm.S, and never be used elsewhere, so declare the 255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project prototypes here. */ 265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectextern int biosdisk_int13_extensions (int ax, int drive, void *dap); 275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectextern int biosdisk_standard (int ah, int drive, 285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project int coff, int hoff, int soff, 295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project int nsec, int segment); 305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectextern int check_int13_extensions (int drive); 315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectextern int get_diskinfo_standard (int drive, 325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long *cylinders, 335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long *heads, 345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long *sectors); 355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if 0 365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectextern int get_diskinfo_floppy (int drive, 375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long *cylinders, 385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long *heads, 395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long *sectors); 405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif 415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Read/write NSEC sectors starting from SECTOR in DRIVE disk with GEOMETRY 445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project from/into SEGMENT segment. If READ is BIOSDISK_READ, then read it, 455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project else if READ is BIOSDISK_WRITE, then write it. If an geometry error 465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project occurs, return BIOSDISK_ERROR_GEOMETRY, and if other error occurs, then 475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project return the error number. Otherwise, return 0. */ 485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint 495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectbiosdisk (int read, int drive, struct geometry *geometry, 505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project int sector, int nsec, int segment) 515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{ 525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project int err; 535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (geometry->flags & BIOSDISK_FLAG_LBA_EXTENSION) 555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project struct disk_address_packet 575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char length; 595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char reserved; 605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned short blocks; 615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long buffer; 625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long long block; 635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } __attribute__ ((packed)) dap; 645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* XXX: Don't check the geometry by default, because some buggy 665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project BIOSes don't return the number of total sectors correctly, 675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project even if they have working LBA support. Hell. */ 685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef NO_BUGGY_BIOS_IN_THE_WORLD 695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (sector >= geometry->total_sectors) 705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project return BIOSDISK_ERROR_GEOMETRY; 715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* NO_BUGGY_BIOS_IN_THE_WORLD */ 725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* FIXME: sizeof (DAP) must be 0x10. Should assert that the compiler 745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project can't add any padding. */ 755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project dap.length = sizeof (dap); 765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project dap.block = sector; 775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project dap.blocks = nsec; 785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project dap.reserved = 0; 795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* This is undocumented part. The address is formated in 805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project SEGMENT:ADDRESS. */ 815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project dap.buffer = segment << 16; 825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project err = biosdisk_int13_extensions ((read + 0x42) << 8, drive, &dap); 845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* #undef NO_INT13_FALLBACK */ 865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifndef NO_INT13_FALLBACK 875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (err) 885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (geometry->flags & BIOSDISK_FLAG_CDROM) 905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project return err; 915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->flags &= ~BIOSDISK_FLAG_LBA_EXTENSION; 935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->total_sectors = (geometry->cylinders 945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * geometry->heads 955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * geometry->sectors); 965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project return biosdisk (read, drive, geometry, sector, nsec, segment); 975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } 985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* ! NO_INT13_FALLBACK */ 995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 1005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } 1015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project else 1025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 1035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project int cylinder_offset, head_offset, sector_offset; 1045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project int head; 1055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 1065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* SECTOR_OFFSET is counted from one, while HEAD_OFFSET and 1075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project CYLINDER_OFFSET are counted from zero. */ 1085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project sector_offset = sector % geometry->sectors + 1; 1095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project head = sector / geometry->sectors; 1105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project head_offset = head % geometry->heads; 1115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project cylinder_offset = head / geometry->heads; 1125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 1135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (cylinder_offset >= geometry->cylinders) 1145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project return BIOSDISK_ERROR_GEOMETRY; 1155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 1165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project err = biosdisk_standard (read + 0x02, drive, 1175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project cylinder_offset, head_offset, sector_offset, 1185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project nsec, segment); 1195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } 1205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 1215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project return err; 1225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project} 1235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 1245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Check bootable CD-ROM emulation status. */ 1255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int 1265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectget_cdinfo (int drive, struct geometry *geometry) 1275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{ 1285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project int err; 1295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project struct iso_spec_packet 1305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 1315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char size; 1325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char media_type; 1335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char drive_no; 1345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char controller_no; 1355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long image_lba; 1365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned short device_spec; 1375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned short cache_seg; 1385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned short load_seg; 1395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned short length_sec512; 1405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char cylinders; 1415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char sectors; 1425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char heads; 1435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 1445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char dummy[16]; 1455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } __attribute__ ((packed)) cdrp; 1465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 1475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project grub_memset (&cdrp, 0, sizeof (cdrp)); 1485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project cdrp.size = sizeof (cdrp) - sizeof (cdrp.dummy); 1495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project err = biosdisk_int13_extensions (0x4B01, drive, &cdrp); 1505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (! err && cdrp.drive_no == drive) 1515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 1525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if ((cdrp.media_type & 0x0F) == 0) 1535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 1545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* No emulation bootable CD-ROM */ 1555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION | BIOSDISK_FLAG_CDROM; 1565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->cylinders = 0; 1575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->heads = 1; 1585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->sectors = 15; 1595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->sector_size = 2048; 1605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->total_sectors = MAXINT; 1615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project return 1; 1625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } 1635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project else 1645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 1655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* Floppy or hard-disk emulation */ 1665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->cylinders 1675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project = ((unsigned int) cdrp.cylinders 1685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project + (((unsigned int) (cdrp.sectors & 0xC0)) << 2)); 1695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->heads = cdrp.heads; 1705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->sectors = cdrp.sectors & 0x3F; 1715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->sector_size = SECTOR_SIZE; 1725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->total_sectors = (geometry->cylinders 1735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * geometry->heads 1745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * geometry->sectors); 1755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project return -1; 1765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } 1775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } 1785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project return 0; 1795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project} 1805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 1815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Return the geometry of DRIVE in GEOMETRY. If an error occurs, return 1825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project non-zero, otherwise zero. */ 1835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint 1845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectget_diskinfo (int drive, struct geometry *geometry) 1855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{ 1865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project int err; 1875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 1885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* Clear the flags. */ 1895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->flags = 0; 1905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 1915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (drive & 0x80) 1925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 1935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* hard disk or CD-ROM */ 1945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project int version; 1955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long total_sectors = 0; 1965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 1975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project version = check_int13_extensions (drive); 1985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 1995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (drive >= 0x88 || version) 2005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 2015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* Possible CD-ROM - check the status. */ 2025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (get_cdinfo (drive, geometry)) 2035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project return 0; 2045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } 2055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 2065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (version) 2075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 2085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project struct drive_parameters 2095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 2105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned short size; 2115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned short flags; 2125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long cylinders; 2135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long heads; 2145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long sectors; 2155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long long total_sectors; 2165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned short bytes_per_sector; 2175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* ver 2.0 or higher */ 2185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned long EDD_configuration_parameters; 2195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* ver 3.0 or higher */ 2205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned short signature_dpi; 2215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char length_dpi; 2225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char reserved[3]; 2235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char name_of_host_bus[4]; 2245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char name_of_interface_type[8]; 2255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char interface_path[8]; 2265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char device_path[8]; 2275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char reserved2; 2285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char checksum; 2295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 2305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* XXX: This is necessary, because the BIOS of Thinkpad X20 2315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project writes a garbage to the tail of drive parameters, 2325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project regardless of a size specified in a caller. */ 2335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project unsigned char dummy[16]; 2345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } __attribute__ ((packed)) drp; 2355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 2365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* It is safe to clear out DRP. */ 2375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project grub_memset (&drp, 0, sizeof (drp)); 2385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 2395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* PhoenixBIOS 4.0 Revision 6.0 for ZF Micro might understand 2405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project the greater buffer size for the "get drive parameters" int 2415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 0x13 call in its own way. Supposedly the BIOS assumes even 2425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project bigger space is available and thus corrupts the stack. 2435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project This is why we specify the exactly necessary size of 0x42 2445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project bytes. */ 2455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project drp.size = sizeof (drp) - sizeof (drp.dummy); 2465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 2475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project err = biosdisk_int13_extensions (0x4800, drive, &drp); 2485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (! err) 2495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 2505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* Set the LBA flag. */ 2515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION; 2525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 2535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* I'm not sure if GRUB should check the bit 1 of DRP.FLAGS, 2545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project so I omit the check for now. - okuji */ 2555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* if (drp.flags & (1 << 1)) */ 2565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 2575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* FIXME: when the 2TB limit becomes critical, we must 2585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project change the type of TOTAL_SECTORS to unsigned long 2595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project long. */ 2605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (drp.total_sectors) 2615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project total_sectors = drp.total_sectors & ~0L; 2625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project else 2635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* Some buggy BIOSes doesn't return the total sectors 2645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project correctly but returns zero. So if it is zero, compute 2655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project it by C/H/S returned by the LBA BIOS call. */ 2665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project total_sectors = drp.cylinders * drp.heads * drp.sectors; 2675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } 2685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } 2695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 2705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* Don't pass GEOMETRY directly, but pass each element instead, 2715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project so that we can change the structure easily. */ 2725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project err = get_diskinfo_standard (drive, 2735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project &geometry->cylinders, 2745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project &geometry->heads, 2755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project &geometry->sectors); 2765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (err) 2775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project return err; 2785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 2795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (! total_sectors) 2805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 2815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project total_sectors = (geometry->cylinders 2825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * geometry->heads 2835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * geometry->sectors); 2845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } 2855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->total_sectors = total_sectors; 2865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->sector_size = SECTOR_SIZE; 2875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } 2885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project else 2895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project { 2905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* floppy disk */ 2915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 2925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* First, try INT 13 AH=8h call. */ 2935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project err = get_diskinfo_standard (drive, 2945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project &geometry->cylinders, 2955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project &geometry->heads, 2965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project &geometry->sectors); 2975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 2985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if 0 2995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project /* If fails, then try floppy-specific probe routine. */ 3005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (err) 3015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project err = get_diskinfo_floppy (drive, 3025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project &geometry->cylinders, 3035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project &geometry->heads, 3045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project &geometry->sectors); 3055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif 3065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 3075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project if (err) 3085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project return err; 3095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 3105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->total_sectors = (geometry->cylinders 3115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * geometry->heads 3125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * geometry->sectors); 3135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project geometry->sector_size = SECTOR_SIZE; 3145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project } 3155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project 3165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project return 0; 3175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project} 318