📄 ide.c
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-2000 Microsoft Corporation
Module Name: ide.c
Abstract: Boot loader IDE/ATA access functions.
Functions:
id_drive - Locate/identify drive.
lba_to_pchs - Convert LBA address to Physical CHS.
read_sector - Read the contents of a disk sector.
init_ide - Initialize IDE drive.
load_image_ide - Load OS image from drive.
OEMHDDPlatformInit - Blcommon interface functions.
OEMHDDPreDownload - "
OEMHDDReadData - "
OEMHDDLaunch - "
Notes:
Assumptions:
- only primary master drive is supported
- FAT16
- file op routines only work on a single file at a time
- kernel image is in the root directory with the bootloader image
--*/
#include <windows.h>
#include "bootarg.h"
#include "ide.h"
#include "fat.h"
#include "bldr.h"
// Global variables.
//
UCHAR g_bsect[SECTOR_SIZE];
ULONG g_sectorsread=0;
UCHAR g_bstartcounting=0;
STATUSBAR g_statbar;
// Function prototypes.
//
int create_statusbar(PSTATUSBAR pbar, ULONG sval, ULONG eval);
int update_statusbar(PSTATUSBAR pbar, ULONG cval);
// Externs.
//
extern FILEINFO g_fileinfo;
int id_drive(void)
{
USHORT cnt=0;
drv_id_hdr hdr;
DEBUGMSG(ZONE_BOOTPROG, (TEXT("B6\r\n")));
memset(&hdr, 0, sizeof(drv_id_hdr));
// Denote drive of interest and get drive id information
WAIT_IDE_BUSY;
WAIT_IDE_NOT_DRDY;
// TODO - compensate for other drive numbers.
WRITE_IDE_UCHAR(IDE_DRVHD_REG, 0xA0);
WRITE_IDE_UCHAR(IDE_CMD_REG, IDE_IDDRIVE_CMD);
WAIT_IDE_BUSY;
WAIT_IDE_NOT_DRQ;
DEBUGMSG(ZONE_BOOTPROG, (TEXT("B7\r\n")));
if(IS_IDE_ERROR)
{
RETAILMSG(1, (TEXT("ERROR: Drive ID failed.\r\n")));
return(-1);
}
DEBUGMSG(ZONE_BOOTPROG, (TEXT("B8\r\n")));
// Read id info from IDE sector buffer
for(cnt = 0 ; cnt < (sizeof(drv_id_hdr) / sizeof(USHORT)) ; cnt++)
*((USHORT *)(&hdr) + cnt) = READ_IDE_USHORT(IDE_DATA_REG);
// Save away P-CHS conversion information for the drive.
g_drvparms.phy_cyls = hdr.lcyls;
g_drvparms.phy_heads = hdr.lheads;
g_drvparms.phy_sectspertrk = hdr.lsctptrk;
DEBUGMSG(ZONE_INFO, (TEXT("lheads = 0x%x\r\n"), g_drvparms.phy_heads));
DEBUGMSG(ZONE_INFO, (TEXT("lsctptrk = 0x%x\r\n"), g_drvparms.phy_sectspertrk));
RETAILMSG(1, (TEXT("Loading image from hard drive...\r\n")));
return(0);
}
int lba_to_pchs(ULONG lba,
USHORT *pc,
UCHAR *ph,
UCHAR *ps)
{
USHORT temp = 0;
// Make sure we know the drive geometry
if (g_drvparms.phy_cyls == 0 ||
g_drvparms.phy_heads == 0 ||
g_drvparms.phy_sectspertrk == 0)
return(-1);
if (pc == NULL || ph == NULL || ps == NULL)
return(-1);
// Do the math...
*pc = (USHORT)(lba / (g_drvparms.phy_heads * g_drvparms.phy_sectspertrk));
temp = (USHORT)(lba % (g_drvparms.phy_heads * g_drvparms.phy_sectspertrk));
*ph = (UCHAR)(temp / g_drvparms.phy_sectspertrk);
*ps = (UCHAR)(temp % g_drvparms.phy_sectspertrk) + 1;
return(0);
}
int read_sector(ULONG lba, unsigned char *pbuf)
{
USHORT c = 0;
UCHAR h = 0;
UCHAR s = 0;
USHORT i = 0;
UCHAR *a = NULL;
if (!pbuf)
return(-1);
// Convert LBA address to P-CHS for IDE controller
if (lba_to_pchs(lba, &c, &h, &s))
return(-1);
DEBUGMSG(ZONE_INFO, (TEXT("INFO: Reading sector (P-CHS = 0x%x:0x%x:0x%x).\r\n"), c, h, s));
// Program the IDE controller
WAIT_IDE_BUSY;
WRITE_IDE_UCHAR(IDE_CYLL_REG, (unsigned char)(c & 0x00ff));
WRITE_IDE_UCHAR(IDE_CYLH_REG, (unsigned char)((c & 0xff00) >> 8));
// TODO - future drive num compensate.
WRITE_IDE_UCHAR(IDE_DRVHD_REG, (unsigned char)(h | 0xA0));
WRITE_IDE_UCHAR(IDE_SECTNUM_REG, (UCHAR)s);
WRITE_IDE_UCHAR(IDE_SECTCNT_REG, 1);
// Make sure interrupt enable bit is off (we'll poll)
_outp(0x3f6, 0x0a);
WAIT_IDE_NOT_DRDY;
WRITE_IDE_UCHAR(IDE_CMD_REG, IDE_RDSECT_CMD);
WAIT_IDE_BUSY;
if (IS_IDE_ERROR)
{
RETAILMSG(1, (TEXT("ERROR: Sector read failed.\r\n")));
return(-1);
}
WAIT_IDE_NOT_DRQ;
// Copy sector buffer contents to callers buffer
for(i=0 ; i < (SECTOR_SIZE / sizeof(USHORT)) ; i++)
*((USHORT *)pbuf + i) = (USHORT)(READ_IDE_USHORT(IDE_DATA_REG));
// Increment total number of sectors and update status bar
if (g_bstartcounting)
{
++g_sectorsread;
update_statusbar(&g_statbar, g_sectorsread);
}
return(0);
}
int init_ide(void)
{
// Get drive geometry info - needed for LBA -> P-CHS convertion
if (id_drive())
return(-1);
return(0);
}
// TODO: Resolve with OEMHDDPreDownload.
int load_image_ide(unsigned char *pname, ULONG *pimgloc)
{
int stat=0;
IMGHDR imghdr;
RECHDR rechdr;
ULONG cnt = 0;
DEBUGMSG(ZONE_BOOTPROG, (TEXT("B5\r\n")));
//
g_bstartcounting = 0;
g_sectorsread = 0;
// Initialize IDE
if (init_ide())
{
RETAILMSG(1, (TEXT("ERROR: IDE device initialization failed.\r\n")));
return(-1);
}
// Initialize FAT structs
if (init_fat())
{
RETAILMSG(1, (TEXT("ERROR: FAT initialization failed.\r\n")));
return(-1);
}
// Open image (finds starting LBA and size - inits structs for later ops)
// Only read is supported
if (file_open(pname))
{
RETAILMSG(1, (TEXT("ERROR: File open failed (%s)\r\n"), pname));
return(-1);
}
// Display status bar
create_statusbar(&g_statbar, 0, (g_fileinfo.fsize / SECTOR_SIZE) - 1);
g_bstartcounting = 1;
// Get image header
stat = file_read((unsigned char *)&imghdr, sizeof(IMGHDR));
if (stat == FAT_EOF)
{
RETAILMSG(1, (TEXT("ERROR: EOF reading image header.\r\n")));
return(-1);
}
else if (stat)
{
RETAILMSG(1, (TEXT("ERROR: File read failed.\r\n")));
return(-1);
}
// Determine jump address
*pimgloc = imghdr.imgaddr;
// Display image header
DEBUGMSG(ZONE_INFO, (TEXT("Image Header:\r\n")));
DEBUGMSG(ZONE_INFO, (TEXT("-------------------------------------------\r\n")));
DEBUGMSG(ZONE_INFO, (TEXT("Sync Bytes = '%c%c%c%c%c%c'\r\n"), imghdr.syncbytes[0], imghdr.syncbytes[1], imghdr.syncbytes[2], imghdr.syncbytes[3], imghdr.syncbytes[4], imghdr.syncbytes[5]));
DEBUGMSG(ZONE_INFO, (TEXT("Image Address = 0x%x\r\n"), imghdr.imgaddr));
DEBUGMSG(ZONE_INFO, (TEXT("Image Length = 0x%x\r\n"), imghdr.imglen));
do
{
// Get record header
stat = file_read((unsigned char *)&rechdr, sizeof(RECHDR));
if (stat == FAT_EOF)
{
RETAILMSG(1, (TEXT("ERROR: EOF reading record header.\r\n")));
return(-1);
}
else if (stat)
{
RETAILMSG(1, (TEXT("ERROR: File read failed.\r\n")));
return(-1);
}
// Display Record Header
DEBUGMSG(ZONE_INFO, (TEXT("Record Header:\r\n")));
DEBUGMSG(ZONE_INFO, (TEXT("------------------------------------------\r\n")));
DEBUGMSG(ZONE_INFO, (TEXT("Record Address = 0x%x\r\n"), rechdr.recaddr));
DEBUGMSG(ZONE_INFO, (TEXT("Record Length = 0x%x\r\n"), rechdr.reclen));
DEBUGMSG(ZONE_INFO, (TEXT("Record CheckSum = 0x%x\r\n"), rechdr.recchksum));
// Last Header
if (rechdr.recaddr == 0 && rechdr.recchksum == 0)
break;
stat = file_read((unsigned char *)rechdr.recaddr, rechdr.reclen);
if (stat)
{
if (stat == EOF)
RETAILMSG(1, (TEXT("ERROR: EOF reading data.\r\n")));
else
RETAILMSG(1, (TEXT("ERROR: File read failed.\r\n")));
return(-1);
}
}
while(1);
// Close file
file_close();
return(0);
}
BOOL OEMHDDPlatformInit(VOID)
{
return(TRUE);
}
DWORD OEMHDDPreDownload(VOID)
{
UCHAR pName[] = KIMAGE_NAME;
//
g_bstartcounting = 0;
g_sectorsread = 0;
// Initialize IDE
if (init_ide())
{
RETAILMSG(1, (TEXT("ERROR: IDE device initialization failed.\r\n")));
return(-1);
}
// Initialize FAT structs
if (init_fat())
{
RETAILMSG(1, (TEXT("ERROR: FAT initialization failed.\r\n")));
return(-1);
}
// Open image (finds starting LBA and size - inits structs for later ops)
// Only read is supported
if (file_open(pName))
{
RETAILMSG(1, (TEXT("ERROR: File open failed (%s).\r\n"), pName));
return(-1);
}
// Display status bar
create_statusbar(&g_statbar, 0, (g_fileinfo.fsize / SECTOR_SIZE) - 1);
g_bstartcounting = 1;
return(BL_DOWNLOAD);
}
BOOL OEMHDDReadData(DWORD cbData, LPBYTE pbData)
{
int stat=0;
stat = file_read((unsigned char *)pbData, cbData);
if (stat == FAT_EOF)
{
RETAILMSG(1, (TEXT("ERROR: EOF reading record header.\r\n")));
return(FALSE);
}
else if (stat)
{
RETAILMSG(1, (TEXT("ERROR: File read failed.\r\n")));
return(FALSE);
}
return(TRUE);
}
VOID OEMHDDLaunch(DWORD dwImageStart,
DWORD dwImageLength,
DWORD dwLaunchAddr,
const ROMHDR *pRomHdr)
{
((PFN_LAUNCH)(dwLaunchAddr))();
// Should never be reached.
SpinForever();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -