?? bootpart.cpp
字號:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
extern "C" // hmseo-061028
{
#include <WMRConfig.h>
#include <WMRTypes.h>
}
#include <bootpart.h>
#include "bppriv.h"
LPBYTE g_pbMBRSector = NULL;
LPBYTE g_pbBlock = NULL;
DWORD g_dwMBRSectorNum = INVALID_ADDR;
FlashInfo g_FlashInfo;
PARTSTATE g_partStateTable[NUM_PARTS];
PSectorInfo g_pSectorInfoBuf;
DWORD g_dwLastLogSector; // Stores the last valid logical sector
DWORD g_dwDataBytesPerBlock;
DWORD g_dwLastWrittenLoc; // Stores the byte address of the last physical flash address written to
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static Addr LBAtoCHS(FlashInfo *pFlashInfo, Addr lba)
{
if(lba.type == CHS)
return lba;
Addr chs;
DWORD tmp = pFlashInfo->dwNumBlocks * pFlashInfo->wSectorsPerBlock;
chs.type = CHS;
chs.chs.cylinder = (WORD)(lba.lba / tmp);
tmp = lba.lba % tmp;
chs.chs.head = (WORD)(tmp / pFlashInfo->wSectorsPerBlock);
chs.chs.sector = (WORD)((tmp % pFlashInfo->wSectorsPerBlock) + 1);
return chs;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static Addr CHStoLBA(FlashInfo *pFlashInfo, Addr chs)
{
Addr lba;
if(chs.type == LBA)
return chs;
lba.type = LBA;
lba.lba = ((chs.chs.cylinder * pFlashInfo->dwNumBlocks + chs.chs.head)
* pFlashInfo->wSectorsPerBlock)+ chs.chs.sector - 1;
return lba;
}
#define Log2Phys(sector) (sector)
#define SECTOR_TO_BLOCK(sector) ((sector) / (SECTORS_PER_SUPAGE*PAGES_PER_SUBLK) )
#define BLOCK_TO_SECTOR(block) ((block) * (SECTORS_PER_SUPAGE*PAGES_PER_SUBLK) )
extern BOOL WriteBlock(DWORD dwBlock, LPBYTE pbBlock, PSectorInfo pSectorInfoTable);
extern BOOL ReadBlock(DWORD dwBlock, LPBYTE pbBlock, PSectorInfo pSectorInfoTable);
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static BOOL WriteMBR()
{
DWORD dwMBRBlockNum = g_dwMBRSectorNum / g_FlashInfo.wSectorsPerBlock;
RETAILMSG(1, (TEXT("WriteMBR: MBR block = 0x%x.\r\n"), dwMBRBlockNum));
memset (g_pbBlock, 0xff, g_dwDataBytesPerBlock);
memset (g_pSectorInfoBuf, 0xff, sizeof(SectorInfo) * g_FlashInfo.wSectorsPerBlock);
// No need to check return, since a failed read means data hasn't been written yet.
ReadBlock (dwMBRBlockNum, g_pbBlock, g_pSectorInfoBuf);
if (!FMD_EraseBlock (dwMBRBlockNum)) {
RETAILMSG (1, (TEXT("CreatePartition: error erasing block 0x%x\r\n"), dwMBRBlockNum));
return FALSE;
}
memcpy (g_pbBlock + (g_dwMBRSectorNum % g_FlashInfo.wSectorsPerBlock) * g_FlashInfo.wDataBytesPerSector, g_pbMBRSector, g_FlashInfo.wDataBytesPerSector);
g_pSectorInfoBuf->bOEMReserved &= ~OEM_BLOCK_READONLY;
g_pSectorInfoBuf->wReserved2 &= ~SECTOR_WRITE_COMPLETED;
g_pSectorInfoBuf->dwReserved1 = 0;
RETAILMSG(1, (TEXT("WriteBlock: dwMBRBlockNum = 0x%x.\r\n"), dwMBRBlockNum));
#if 0
for (DWORD i = 0; i < 512; i++) {
if (i % 16 == 0)
RETAILMSG(1, (L"0x%x: ", g_pbBlock+i));
RETAILMSG(1, (L"%x%x ", (g_pbBlock[i] >> 4) & 0x0f, g_pbBlock[i] & 0x0f));
if ((i + 1) % 16 == 0)
RETAILMSG(1, (L"\r\n"));
}
#endif
if (!WriteBlock (dwMBRBlockNum, g_pbBlock, g_pSectorInfoBuf)) {
RETAILMSG (1, (TEXT("CreatePartition: could not write to block 0x%x\r\n"), dwMBRBlockNum));
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL CreateMBR()
{
// This, plus a valid partition table, is all the CE partition manager needs to recognize
// the MBR as valid. It does not contain boot code.
memset (g_pbMBRSector, 0xff, g_FlashInfo.wDataBytesPerSector);
g_pbMBRSector[0] = 0xE9;
g_pbMBRSector[1] = 0xfd;
g_pbMBRSector[2] = 0xff;
g_pbMBRSector[SECTOR_SIZE-2] = 0x55;
g_pbMBRSector[SECTOR_SIZE-1] = 0xAA;
// Zero out partition table so that mspart treats entries as empty.
memset (g_pbMBRSector+PARTTABLE_OFFSET, 0, sizeof(PARTENTRY) * NUM_PARTS);
return WriteMBR();
}
BOOL IsValidMBR()
{
// Check to see if the MBR is valid
// MBR block is always located at logical sector 0
#if 0 // hmseo-061029
g_dwMBRSectorNum = 0; //GetMBRSectorNum();
#else // hmseo-061029
// g_dwMBRSectorNum = BLOCK_TO_SECTOR(FTL_AREA_START); // hmseo-061029 set the MBR sector to FTL area start sector.
#endif // hmseo-061029
RETAILMSG (1, (TEXT("IsValidMBR: MBR sector = 0x%x\r\n"), g_dwMBRSectorNum));
if ((g_dwMBRSectorNum == INVALID_ADDR) || !FMD_ReadSector (g_dwMBRSectorNum, g_pbMBRSector, NULL, 1)) {
return FALSE;
}
#if 0
LPBYTE pbBuf = g_pbMBRSector + 512 - 0x42;
RETAILMSG(1, (L"g_pbMBRSector = 0x%x\r\n", g_pbMBRSector));
for (DWORD i = 0; i < 0x40; i++) {
if (i % 16 == 0)
RETAILMSG(1, (L"0x%x: ", pbBuf+i));
RETAILMSG(1, (L"%x%x ", (pbBuf[i] >> 4) & 0x0f, pbBuf[i] & 0x0f));
if ((i + 1) % 16 == 0)
RETAILMSG(1, (L"\r\n"));
}
#endif
return ((g_pbMBRSector[0] == 0xE9) &&
(g_pbMBRSector[1] == 0xfd) &&
(g_pbMBRSector[2] == 0xff) &&
(g_pbMBRSector[SECTOR_SIZE-2] == 0x55) &&
(g_pbMBRSector[SECTOR_SIZE-1] == 0xAA));
}
BOOL IsValidMBRSector(DWORD dwBlock)
{
g_dwMBRSectorNum = BLOCK_TO_SECTOR(dwBlock);
return IsValidMBR();
}
static BOOL IsValidPart (PPARTENTRY pPartEntry)
{
return (pPartEntry->Part_FileSystem != 0xff) && (pPartEntry->Part_FileSystem != 0);
}
/* AddPartitionTableEntry
*
* Generates the partition entry for the partition table and copies the entry
* into the MBR that is stored in memory.
*
*
* ENTRY
* entry - index into partition table
* startSector - starting logical sector
* totalSectors - total logical sectors
* fileSystem - type of partition
* bootInd - byte in partition entry that stores various flags such as
* active and read-only status.
*
* EXIT
*/
static void AddPartitionTableEntry(DWORD entry, DWORD startSector, DWORD totalSectors, BYTE fileSystem, BYTE bootInd)
{
PARTENTRY partentry = {0};
Addr startAddr;
Addr endAddr;
ASSERT(entry < 4);
// no checking with disk info and start/total sectors because we allow
// bogus partitions for testing purposes
// initially known partition table entry
partentry.Part_BootInd = bootInd;
partentry.Part_FileSystem = fileSystem;
partentry.Part_StartSector = startSector;
partentry.Part_TotalSectors = totalSectors;
// logical block addresses for the first and final sector (start on the second head)
startAddr.type = LBA;
startAddr.lba = partentry.Part_StartSector;
endAddr.type = LBA;
endAddr.lba = partentry.Part_StartSector + partentry.Part_TotalSectors-1;
// translate the LBA addresses to CHS addresses
startAddr = LBAtoCHS(&g_FlashInfo, startAddr);
endAddr = LBAtoCHS(&g_FlashInfo, endAddr);
// starting address
partentry.Part_FirstTrack = (BYTE)(startAddr.chs.cylinder & 0xFF);
partentry.Part_FirstHead = (BYTE)(startAddr.chs.head & 0xFF);
// lower 6-bits == sector, upper 2-bits = cylinder upper 2-bits of 10-bit cylinder #
partentry.Part_FirstSector = (BYTE)((startAddr.chs.sector & 0x3F) | ((startAddr.chs.cylinder & 0x0300) >> 2));
// ending address:
partentry.Part_LastTrack = (BYTE)(endAddr.chs.cylinder & 0xFF);
partentry.Part_LastHead = (BYTE)(endAddr.chs.head & 0xFF);
// lower 6-bits == sector, upper 2-bits = cylinder upper 2-bits of 10-bit cylinder #
partentry.Part_LastSector = (BYTE)((endAddr.chs.sector & 0x3F) | ((endAddr.chs.cylinder & 0x0300) >> 2));
memcpy(g_pbMBRSector+PARTTABLE_OFFSET+(sizeof(PARTENTRY)*entry), &partentry, sizeof(PARTENTRY));
}
/* GetPartitionTableIndex
*
* Get the partition index for a particular partition type and active status.
* If partition is not found, then the index of the next free partition in the
* partition table of the MBR is returned.
*
*
* ENTRY
* dwPartType - type of partition
* fActive - TRUE indicates the active partition. FALSE indicates inactive.
*
* EXIT
* pdwIndex - Contains the index of the partition if found. If not found,
* contains the index of the next free partition
* returns TRUE if partition found. FALSE if not found.
*/
static BOOL GetPartitionTableIndex (DWORD dwPartType, BOOL fActive, PDWORD pdwIndex)
{
PPARTENTRY pPartEntry = (PPARTENTRY)(g_pbMBRSector + PARTTABLE_OFFSET);
DWORD iEntry = 0;
for (iEntry = 0; iEntry < NUM_PARTS; iEntry++, pPartEntry++) {
if ((pPartEntry->Part_FileSystem == dwPartType) && (((pPartEntry->Part_BootInd & PART_IND_ACTIVE) != 0) == fActive)) {
*pdwIndex = iEntry;
return TRUE;
}
if (!IsValidPart (pPartEntry)) {
*pdwIndex = iEntry;
return FALSE;
}
}
return FALSE;
}
/* WriteLogicalNumbers
*
* Writes a range of logical sector numbers
*
* ENTRY
* dwStartSector - starting logical sector
* dwNumSectors - number of logical sectors to mark
* fReadOnly - TRUE indicates to mark read-only. FALSE to mark not read-only
*
* EXIT
* TRUE on success
*/
static BOOL WriteLogicalNumbers (DWORD dwStartSector, DWORD dwNumSectors, BOOL fReadOnly)
{
DWORD dwNumSectorsWritten = 0;
DWORD dwPhysSector = Log2Phys (dwStartSector);
DWORD dwBlockNum = dwPhysSector / g_FlashInfo.wSectorsPerBlock;
DWORD dwOffset = dwPhysSector % g_FlashInfo.wSectorsPerBlock;
while (dwNumSectorsWritten < dwNumSectors) {
// If bad block, move to the next block
#if 0
if (IS_BLOCK_UNUSABLE (dwBlockNum)) {
dwBlockNum++;
continue;
}
#endif
memset (g_pbBlock, 0xff, g_dwDataBytesPerBlock);
memset (g_pSectorInfoBuf, 0xff, sizeof(SectorInfo) * g_FlashInfo.wSectorsPerBlock);
// No need to check return, since a failed read means data hasn't been written yet.
ReadBlock (dwBlockNum, g_pbBlock, g_pSectorInfoBuf);
if (!FMD_EraseBlock (dwBlockNum)) {
return FALSE;
}
DWORD dwSectorsToWrite = g_FlashInfo.wSectorsPerBlock - dwOffset;
PSectorInfo pSectorInfo = g_pSectorInfoBuf + dwOffset;
// If this is the last block, then calculate sectors to write if there isn't a full block to update
if ((dwSectorsToWrite + dwNumSectorsWritten) > dwNumSectors)
dwSectorsToWrite = dwNumSectors - dwNumSectorsWritten;
for (DWORD iSector = 0; iSector < dwSectorsToWrite; iSector++, pSectorInfo++, dwNumSectorsWritten++) {
// Assert read only by setting bit to 0 to prevent wear-leveling by FAL
if (fReadOnly)
pSectorInfo->bOEMReserved &= ~OEM_BLOCK_READONLY;
// Set to write completed so FAL can map the sector
pSectorInfo->wReserved2 &= ~SECTOR_WRITE_COMPLETED;
// Write the logical sector number
pSectorInfo->dwReserved1 = dwStartSector + dwNumSectorsWritten;
}
if (!WriteBlock (dwBlockNum, g_pbBlock, g_pSectorInfoBuf))
return FALSE;
dwOffset = 0;
dwBlockNum++;
}
return TRUE;
}
/* CreatePartition
*
* Creates a new partition. If it is a boot section partition, then it formats
* flash.
*
* ENTRY
* dwStartSector - Logical sector to start the partition. NEXT_FREE_LOC if
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -