2019-09-03 11:58:42 +02:00
/*++
Slice 2011
LegacyBoot . c - support for boot legacy OS such as WindowsXP and Linux
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Portion from XOM project
Copyright ( c ) 2006 JLA
*/
2020-08-17 21:40:52 +02:00
# include <Platform.h> // Only use angled for Platform, else, xcode project won't compile
2021-02-06 18:16:46 +01:00
# include <Efi.h>
2019-09-03 11:58:42 +02:00
# include "LegacyBiosThunk.h"
2020-04-16 09:15:26 +02:00
# include "AcpiPatcher.h"
2021-04-28 20:30:34 +02:00
# include "../Settings/Self.h"
# include "../refit/lib.h"
2020-04-16 09:15:26 +02:00
2019-09-03 11:58:42 +02:00
# ifndef DEBUG_ALL
# define DEBUG_LBOOT 1
# else
# define DEBUG_LBOOT DEBUG_ALL
# endif
# if DEBUG_LBOOT == 0
# define DBG(...)
# else
# define DBG(...) DebugLog(0, __VA_ARGS__) // until a better solution is found, force DebugLog(0, ...) to prevent saving to DebugLog, which may cause legacy boot to fail
# endif
# pragma pack(push)
# pragma pack(1)
//template
//CONST MBR_PARTITION_INFO tMBR = {0x80, {0xFE, 0xFF, 0xFF}, 0x06, {0xFE, 0xFF, 0xFF}, 0, 0};
CONST MBR_PARTITION_INFO tMBR = { 0x80 , { 0xFE , 0xFF , 0xFF } , 0xEE , { 0xFE , 0xFF , 0xFF } , 0 , 0 } ;
typedef struct {
UINT8 loader [ 0x1BE ] ;
MBR_PARTITION_INFO p [ 4 ] ;
UINT16 signature ;
} MBR ;
typedef struct {
UINT64 signature ;
UINT32 revision ;
UINT32 headerSize ;
UINT32 headerCRC ;
UINT32 reserved ;
UINT64 myLBA ;
UINT64 alternateLBA ;
UINT64 firstUsableLBA ;
UINT64 lastUsableLBA ;
EFI_GUID diskGUID ;
UINT64 partitionEntryLBA ;
UINT32 numberOfPartitionEntries ;
UINT32 sizeOfPartitionEntry ;
UINT32 partitionEntryArrayCRC32 ;
UINT8 filler [ 4 ] ; //alignment
} GPT_HEADER ;
typedef struct {
EFI_GUID partitionType ;
EFI_GUID partitionGuid ;
UINT64 startingLBA ;
UINT64 endingLBA ;
UINT64 attributes ;
CHAR16 partitionName [ 72 / 2 ] ;
} GPT_ENTRY ;
typedef struct Address_t {
UINT32 offset ;
UINT16 segment ;
UINT8 type ;
} Address ;
// for BIOS INT 13h AH=42h: Extended Read Sectors From Drive
typedef struct {
UINT8 size ; // size of struct = 0x10
UINT8 unused ; // should be 0
UINT16 numSectors ; // number of sectors
UINT16 buffOffset ; // segment and offset to the buffer
UINT16 buffSegment ;
UINT64 lba ; // LBA of starting sector
} BIOS_DISK_ADDRESS_PACKET ;
//located at 0x7F00
CONST UINT8 VideoTest [ ] = {
0xb8 , 0x02 , 0x00 , //mov ax,2
0xcd , 0x10 , //int 0x10
0x66 , 0xbb , 0x0f , 0x00 , 0x00 , 0x00 , //mov ebx, 0x0f
0x66 , 0xb8 , 0x38 , 0x0e , 0x00 , 0x00 , //mov eax, 0x0e38
0x66 , 0xb9 , 0x10 , 0x00 , 0x00 , 0x00 , //mov ecx, 0x10
0xcd , 0x10 , //int 0x10
0xed , 0xe4 , 0xfc //jmp near 0x7c00
} ; //28bytes
# pragma pack(pop)
# define ADDRT_REAL 0 // Segment:Offset (16:16)
# define ADDRT_FLAT 1 // Segment is 0, Offset is 32 bit flat address
EFI_CPU_ARCH_PROTOCOL * mCpu ;
EFI_LEGACY_8259_PROTOCOL * gLegacy8259 ;
THUNK_CONTEXT * mThunkContext = NULL ;
UINT8 * floppyImage ;
EFI_BLOCK_IO * hd82 = NULL ;
EFI_BLOCK_IO * hd80 = NULL ;
EFI_BLOCK_IO * pCDROMBlockIO = NULL ;
EFI_HANDLE hCDROM = NULL ;
Address addrRealFromSegOfs ( UINT16 segment , UINT16 offset ) {
Address address ;
address . segment = segment ;
address . offset = offset ;
address . type = ADDRT_REAL ;
return address ;
}
Address addrFlatFromOffset ( UINT32 offset ) {
Address address ;
address . segment = 0 ;
address . offset = offset ;
address . type = ADDRT_FLAT ;
return address ;
}
Address addrNull ( ) {
Address address ;
address . type = 0xff ;
address . segment = 0 ;
address . offset = 0 ;
return address ;
}
static UINTN addrPagingEnable ;
UINTN addrIsPagingEnabled ( ) {
return addrPagingEnable ;
}
void addrEnablePaging ( UINTN f ) {
addrPagingEnable = f ;
}
# define ADDR_FLAT_MAX addrFlatFromOffset(0xFFFFFFFF)
# define ADDR_FLAT_MIN addrFlatFromOffset(0x00000000)
# define ADDR_REAL_MAX addrRealFromSegOfs(0xFFFF, 0xFFFF)
# define ADDR_REAL_MIN addrRealFromSegOfs(0x0000, 0x0000)
# define ADDR_NULL addrNull()
UINT32 addrToOffset ( Address address ) {
if ( address . type = = ADDRT_REAL )
return ( address . segment < < 4 ) + address . offset ;
if ( address . type = = ADDRT_FLAT )
return addrIsPagingEnabled ( ) ? address . offset & 0x7FFFFFFF : address . offset ;
return 0 ;
}
void * addrToPointer ( Address address ) {
return ( UINT8 * ) ( UINTN ) addrToOffset ( address ) ;
}
static UINTN addrLT ( Address a1 , Address a2 ) { return addrToOffset ( a1 ) < addrToOffset ( a2 ) ; }
//static UINTN addrLTE(Address a1, Address a2) { return addrToOffset(a1) <= addrToOffset(a2); }
//static UINTN addrGT (Address a1, Address a2) { return addrToOffset(a1) > addrToOffset(a2); }
static UINTN addrGTE ( Address a1 , Address a2 ) { return addrToOffset ( a1 ) > = addrToOffset ( a2 ) ; }
//static UINTN addrEQ (Address a1, Address a2) { return addrToOffset(a1) == addrToOffset(a2); }
Address krnMemoryTop ;
/** Reads sectors from given DriveNum with bios into Buffer.
* Requires Dap and Buffer to be allocated in legacy memory region .
*/
EFI_STATUS BiosReadSectorsFromDrive ( UINT8 DriveNum , UINT64 Lba , UINTN NumSectors , BIOS_DISK_ADDRESS_PACKET * Dap , void * Buffer )
{
EFI_STATUS Status ;
IA32_REGISTER_SET Regs ;
// init disk access packet
Dap - > size = sizeof ( BIOS_DISK_ADDRESS_PACKET ) ;
Dap - > unused = 0 ;
Dap - > numSectors = ( UINT16 ) NumSectors ;
Dap - > buffSegment = ( UINT16 ) ( ( ( UINTN ) Buffer > > 16 ) < < 12 ) ;
Dap - > buffOffset = ( UINT16 ) ( UINTN ) Buffer ;
Dap - > lba = Lba ;
// set registers
2020-05-01 18:26:28 +02:00
SetMem ( & Regs , sizeof ( Regs ) , 0 ) ;
2019-09-03 11:58:42 +02:00
// first reset disk controller as the controller seems to be in an undefined state sometimes
2020-04-17 15:14:24 +02:00
DBG ( " Reset disk controller: %hhX \n " , DriveNum ) ;
2019-09-03 11:58:42 +02:00
Regs . H . AH = 0x00 ; // INT 13h AH=00h: Reset disk controller
Regs . H . DL = DriveNum ;
Status = EFI_SUCCESS ;
if ( LegacyBiosInt86 ( 0x13 , & Regs ) ) {
// TRUE = error
2020-04-17 15:14:24 +02:00
DBG ( " Reset 0 disk controller: %hhX \n " , DriveNum ) ;
2019-09-03 11:58:42 +02:00
Regs . H . AH = 0x0D ; // INT 13h AH=00h: Reset disk controller
Regs . H . DL = DriveNum ;
if ( LegacyBiosInt86 ( 0x13 , & Regs ) ) {
Status = EFI_NOT_FOUND ;
DBG ( " reset controller error \n " ) ;
return Status ;
}
}
// next, read sector
Regs . H . AH = 0x42 ; // INT 13h AH=42h: Extended Read Sectors From Drive
Regs . H . DL = DriveNum ;
Regs . E . DS = ( UINT16 ) ( ( ( UINTN ) Dap > > 16 ) < < 12 ) ;
Regs . X . SI = ( UINT16 ) ( UINTN ) Dap ;
2020-04-17 15:14:24 +02:00
// DBG("Drive: %hhX, Dap=%p, Buffer=%p, d.size=%hhX, d.nsect=%d, d.buff=[%hhX:%hhX]\n",
2019-09-03 11:58:42 +02:00
// DriveNum, Dap, Buffer, Dap->size, Dap->numSectors, Dap->buffSegment, Dap->buffOffset);
2020-04-17 15:14:24 +02:00
// DBG("Dap: Reg.DS:SI = [%hhX:%hhX]\n", Regs.E.DS, Regs.X.SI);
2019-09-03 11:58:42 +02:00
Status = EFI_SUCCESS ;
if ( LegacyBiosInt86 ( 0x13 , & Regs ) ) {
// TRUE = error
Regs . H . AH = 0x01 ; // INT 13h AH=01h: Get Status of Last Drive Operation
LegacyBiosInt86 ( 0x13 , & Regs ) ;
Status = EFI_NOT_FOUND ;
}
2020-08-25 17:35:19 +02:00
DBG ( " LegacyBiosInt86 status=%s, AH=%hhX \n " , efiStrError ( Status ) , Regs . H . AH ) ;
2019-09-03 11:58:42 +02:00
return Status ;
}
/** Reads first 2 sectors from given DriveNum with bios and calculates DriveCRC32.
* Requires Dap and Buffer to be allocated in legacy memory region .
*/
EFI_STATUS GetBiosDriveCRC32 ( UINT8 DriveNum ,
UINT32 * DriveCRC32 ,
BIOS_DISK_ADDRESS_PACKET * Dap ,
2020-10-03 19:02:31 +02:00
void * Buffer )
2019-09-03 11:58:42 +02:00
{
EFI_STATUS Status ;
// read first 2 sectors
Status = BiosReadSectorsFromDrive ( DriveNum , 0 , 2 , Dap , Buffer ) ;
if ( ! EFI_ERROR ( Status ) ) {
2019-12-27 18:01:40 +01:00
* DriveCRC32 = GetCrc32 ( ( UINT8 * ) Buffer , 2 * 512 ) ;
2019-09-03 11:58:42 +02:00
//gBS->CalculateCrc32(Buffer, 2 * 512, DriveCRC32);
2020-03-25 19:32:44 +01:00
DBG ( " Bios drive CRC32 = 0x%X \n " , * DriveCRC32 ) ;
2019-09-03 11:58:42 +02:00
}
return Status ;
}
/** Scans bios drives 0x80 and up, calculates CRC32 of first 2 sectors and compares it with Volume->DriveCRC32.
* First 2 sectors whould be enough - covers MBR and GPT header with signatures .
* Requires mThunkContext to be initialiyzed already with InitializeBiosIntCaller ( ) .
*/
UINT8 GetBiosDriveNumForVolume ( REFIT_VOLUME * Volume )
{
EFI_STATUS Status ;
UINT8 DriveNum , BestNum ;
UINT32 DriveCRC32 ;
UINT8 * Buffer ;
BIOS_DISK_ADDRESS_PACKET * Dap ;
UINTN LegacyRegionPages ;
EFI_PHYSICAL_ADDRESS LegacyRegion ;
2020-04-17 15:14:24 +02:00
// DBG("Expected volume CRC32 = %hhX\n", Volume->DriveCRC32);
2019-09-03 11:58:42 +02:00
LegacyRegion = 0x0C0000 ;
LegacyRegionPages = EFI_SIZE_TO_PAGES ( sizeof ( BIOS_DISK_ADDRESS_PACKET ) + 2 * 512 ) + 1 /* dap + 2 sectors */ ;
Status = gBS - > AllocatePages ( AllocateMaxAddress ,
EfiBootServicesData ,
LegacyRegionPages ,
& LegacyRegion
) ;
if ( EFI_ERROR ( Status ) ) {
return 0 ;
}
Dap = ( BIOS_DISK_ADDRESS_PACKET * ) ( UINTN ) LegacyRegion ;
Buffer = ( UINT8 * ) ( UINTN ) ( LegacyRegion + 0x200 ) ;
//Slice - some CD has BIOS driveNum = 0
// scan drives from 0x80
BestNum = 0 ;
for ( DriveNum = 0x80 ; DriveNum < 0x88 ; DriveNum + + ) {
DriveCRC32 = 0 ;
Status = GetBiosDriveCRC32 ( DriveNum , & DriveCRC32 , Dap , Buffer ) ;
if ( EFI_ERROR ( Status ) ) {
// error or no more disks
//DriveNum = 0;
2020-04-17 15:14:24 +02:00
DBG ( " Can't get drive 0x%hhX CRC32 \n " , DriveNum ) ;
2019-09-03 11:58:42 +02:00
continue ;
}
BestNum = DriveNum ;
2020-04-17 15:14:24 +02:00
DBG ( " Calculated CRC=%X at drive 0x%hhX \n " , Volume - > DriveCRC32 , BestNum ) ;
2019-09-03 11:58:42 +02:00
if ( Volume - > DriveCRC32 = = DriveCRC32 ) {
break ;
}
}
gBS - > FreePages ( LegacyRegion , LegacyRegionPages ) ;
2020-04-17 15:14:24 +02:00
DBG ( " Returning Bios drive %hhX \n " , BestNum ) ;
2019-09-03 11:58:42 +02:00
return BestNum ;
}
EFI_STATUS bootElTorito ( REFIT_VOLUME * volume )
{
EFI_BLOCK_IO * pBlockIO = volume - > BlockIO ;
Address bootAddress = addrRealFromSegOfs ( 0x0000 , 0x7C00 ) ;
UINT8 * sectorBuffer ; //[2048];
EFI_STATUS Status = EFI_NOT_FOUND ;
UINT64 lba ;
UINT16 bootLoadSegment ;
Address bootLoadAddress ;
UINT32 bootSize ;
UINT32 bootSectors ;
IA32_REGISTER_SET Regs ;
//UINTN LogSize;
2019-12-21 01:31:49 +01:00
sectorBuffer = ( __typeof__ ( sectorBuffer ) ) AllocateAlignedPages ( EFI_SIZE_TO_PAGES ( 2048 ) , 64 ) ;
2019-09-03 11:58:42 +02:00
krnMemoryTop = addrRealFromSegOfs ( 0xA000 , 0x0000 ) ;
addrEnablePaging ( 0 ) ;
// No device, no game
if ( ! pBlockIO ) {
DBG ( " CDROMBoot: No CDROM to boot from \n " ) ;
if ( sectorBuffer ) {
FreePages ( sectorBuffer , EFI_SIZE_TO_PAGES ( 2048 ) ) ;
}
return Status ;
}
// Load El Torito boot record volume descriptor
Status = pBlockIO - > ReadBlocks ( pBlockIO , pBlockIO - > Media - > MediaId , 0x11 , 2048 , sectorBuffer ) ;
if ( EFI_ERROR ( Status ) ) {
// Retry in case the CD was swapped out
2020-10-03 19:02:31 +02:00
Status = gBS - > HandleProtocol ( volume - > DeviceHandle , & gEfiBlockIoProtocolGuid , ( void * * ) & pBlockIO ) ;
2019-09-03 11:58:42 +02:00
if ( ! EFI_ERROR ( Status ) ) {
// pCDROMBlockIO = pBlockIO;
Status = pBlockIO - > ReadBlocks ( pBlockIO , pBlockIO - > Media - > MediaId , 0x11 , 2048 , sectorBuffer ) ;
}
if ( EFI_ERROR ( Status ) ) {
2020-08-25 17:35:19 +02:00
DBG ( " CDROMBoot: Unable to read block %X: %s \n " , 0x11 , efiStrError ( Status ) ) ;
2019-09-03 11:58:42 +02:00
return Status ;
}
}
if ( AsciiStrCmp ( ( CHAR8 * ) ( sectorBuffer + 0x7 ) , " EL TORITO SPECIFICATION " ) ) {
DBG ( " CDROMBoot: Not an El Torito Specification disk \n " ) ;
return Status ;
}
// Find the boot catalog
lba = sectorBuffer [ 0x47 ] + sectorBuffer [ 0x48 ] * 256 + sectorBuffer [ 0x49 ] * 65536 + sectorBuffer [ 0x4A ] * 16777216 ;
Status = pBlockIO - > ReadBlocks ( pBlockIO , pBlockIO - > Media - > MediaId , lba , 2048 , sectorBuffer ) ;
if ( EFI_ERROR ( Status ) ) {
2020-08-25 17:35:19 +02:00
DBG ( " CDROMBoot: Unable to read block %llX: %s \n " , lba , efiStrError ( Status ) ) ;
2019-09-03 11:58:42 +02:00
return Status ;
}
if ( sectorBuffer [ 0x00 ] ! = 1 | | sectorBuffer [ 0x1E ] ! = 0x55 | | sectorBuffer [ 0x1F ] ! = 0xAA ) {
2020-03-25 19:32:44 +01:00
DBG ( " CDROMBoot: Invalid El Torito validation entry in boot catalog LBA %llX \n " , lba ) ;
2019-09-03 11:58:42 +02:00
// DumpHex(0, 0, 64, sectorBuffer);
return Status ;
}
if ( sectorBuffer [ 0x01 ] ! = 0 ) {
DBG ( " CDROMBoot: Platform mismatch: %d \n " , sectorBuffer [ 0x01 ] ) ;
return Status ;
}
if ( sectorBuffer [ 0x20 ] ! = 0x88 ) {
DBG ( " CDROMBoot: CD-ROM is not bootable \n " ) ;
return Status ;
}
if ( sectorBuffer [ 0x21 ] ! = 0 ) {
DBG ( " CDROMBoot: Currently only non-emulated CDROMs are supported " ) ;
return Status ;
}
bootLoadSegment = sectorBuffer [ 0x22 ] + sectorBuffer [ 0x23 ] * 256 ;
if ( ! bootLoadSegment )
bootLoadSegment = 0x7C0 ;
bootSectors = sectorBuffer [ 0x26 ] + sectorBuffer [ 0x27 ] * 256 ;
bootSize = bootSectors * pBlockIO - > Media - > BlockSize ;
bootLoadAddress = addrRealFromSegOfs ( bootLoadSegment , 0 ) ;
if ( addrLT ( bootLoadAddress , bootAddress ) | | addrGTE ( bootLoadAddress , krnMemoryTop ) ) {
2020-03-25 19:32:44 +01:00
DBG ( " CDROMBoot: Illegal boot load address %XL%X \n " , addrToOffset ( bootLoadAddress ) , bootSize ) ;
2019-09-03 11:58:42 +02:00
return Status ;
}
lba = sectorBuffer [ 0x28 ] + sectorBuffer [ 0x29 ] * 256 + sectorBuffer [ 0x2A ] * 65536 + sectorBuffer [ 0x2B ] * 16777216 ;
2020-03-25 19:32:44 +01:00
DBG ( " CDROMBoot: Booting LBA %llu @%X L%X \n " , lba , addrToOffset ( bootLoadAddress ) , bootSize ) ;
2019-09-03 11:58:42 +02:00
gBS - > FreePages ( ( EFI_PHYSICAL_ADDRESS ) ( UINTN ) sectorBuffer , 1 ) ;
// Read the boot sectors into the boot load address
Status = pBlockIO - > ReadBlocks ( pBlockIO , pBlockIO - > Media - > MediaId , lba , bootSize , addrToPointer ( bootLoadAddress ) ) ;
if ( EFI_ERROR ( Status ) ) {
2020-08-25 17:35:19 +02:00
DBG ( " CDROMBoot: Unable to read block %llu: %s \n " , lba , efiStrError ( Status ) ) ;
2019-09-03 11:58:42 +02:00
return Status ;
}
2020-10-17 15:01:33 +02:00
Status = SaveBooterLog ( & self . getCloverDir ( ) , LEGBOOT_LOG ) ;
2020-10-03 19:02:31 +02:00
// Jief : don't write outside of SelfDir
// if (EFI_ERROR(Status)) {
// DBG("can't save legacy-boot.log\n");
// Status = SaveBooterLog(NULL, LEGBOOT_LOG);
// }
2019-09-03 11:58:42 +02:00
/*LogSize = msgCursor - msgbuf;
2020-10-03 19:02:31 +02:00
Status = egSaveFile ( & self . getSelfRootDir ( ) , LEGBOOT_LOG , ( UINT8 * ) msgbuf , LogSize ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
DBG ( " can't save legacy-boot.log \n " ) ;
Status = egSaveFile ( NULL , LEGBOOT_LOG , ( UINT8 * ) msgbuf , LogSize ) ;
}
*/
// Configure drive
// hd82 = pBlockIO;
// Initialize Registers
// CONTEXT->edx = 0x82;
// Boot it
// dbgStart(bootLoadAddress, enableDebugger);
2020-10-03 19:02:31 +02:00
Status = gBS - > LocateProtocol ( & gEfiLegacy8259ProtocolGuid , NULL , ( void * * ) & gLegacy8259 ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
return Status ;
}
/* mCpu = NULL;
2020-10-03 19:02:31 +02:00
Status = gBS - > LocateProtocol ( & gEfiCpuArchProtocolGuid , NULL , ( void * * ) & mCpu ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
return Status ;
}
*/
2020-10-03 19:02:31 +02:00
Status = gBS - > AllocatePool ( EfiBootServicesData , sizeof ( THUNK_CONTEXT ) , ( void * * ) & mThunkContext ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
Status = InitializeBiosIntCaller ( ) ; //mThunkContext);
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
// InitializeInterruptRedirection(); //gLegacy8259);
// Status = mCpu->EnableInterrupt(mCpu);
Regs . X . DX = 0 ; //0x82;
// Regs.X.SI = (UINT16)activePartition;
//Regs.X.ES = EFI_SEGMENT((UINT32) pBootSector);
//Regs.X.BX = EFI_OFFSET ((UINT32) pBootSector);
// LegacyBiosFarCall86(0, 0x7c00, &Regs);
LegacyBiosFarCall86 (
EFI_SEGMENT ( ( UINT32 ) addrToOffset ( bootLoadAddress ) ) ,
EFI_OFFSET ( ( UINT32 ) addrToOffset ( bootLoadAddress ) ) ,
& Regs
) ;
// Success - Should never get here unless debugger aborts
return Status ;
}
EFI_STATUS bootMBR ( REFIT_VOLUME * volume )
{
EFI_STATUS Status ;
EFI_BLOCK_IO * pDisk = volume - > BlockIO ;
//UINT8* pMBR = (void*)0x600;
UINT8 * pMBR = ( UINT8 * ) ( UINTN ) 0x7C00 ;
//UINT8* pBootSector = (void*)0x7C00;
//MBR_PARTITION_INFO* activePartition = NULL;
//UINTN partitionIndex;
IA32_REGISTER_SET Regs ;
UINTN i , j ;
UINT8 BiosDriveNum ;
//UINTN LogSize;
2020-05-01 18:26:28 +02:00
SetMem ( & Regs , sizeof ( Regs ) , 0 ) ;
2019-09-03 11:58:42 +02:00
addrEnablePaging ( 0 ) ;
2020-10-03 19:02:31 +02:00
Status = gBS - > LocateProtocol ( & gEfiLegacy8259ProtocolGuid , NULL , ( void * * ) & gLegacy8259 ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
return Status ;
}
mCpu = NULL ;
2020-10-03 19:02:31 +02:00
Status = gBS - > LocateProtocol ( & gEfiCpuArchProtocolGuid , NULL , ( void * * ) & mCpu ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
return Status ;
}
2020-10-03 19:02:31 +02:00
Status = gBS - > AllocatePool ( EfiBootServicesData , sizeof ( THUNK_CONTEXT ) , ( void * * ) & mThunkContext ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
2020-08-09 17:55:30 +02:00
DBG ( " boot from partition %ls \n " , FileDevicePathToXStringW ( volume - > DevicePath ) . wc_str ( ) ) ;
2019-09-03 11:58:42 +02:00
Status = InitializeBiosIntCaller ( ) ; //mThunkContext);
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
//InitializeInterruptRedirection(); //gLegacy8259);
//Status = mCpu->EnableInterrupt(mCpu);
// Read the MBR
Status = pDisk - > ReadBlocks ( pDisk , pDisk - > Media - > MediaId , 0 , 512 , pMBR ) ;
if ( EFI_ERROR ( Status ) ) {
2020-08-25 17:35:19 +02:00
DBG ( " HDBoot: Unable to read MBR: %s \n " , efiStrError ( Status ) ) ;
2019-09-03 11:58:42 +02:00
return Status ;
}
for ( i = 0 ; i < 16 ; i + + ) {
2020-03-25 19:32:44 +01:00
DBG ( " %04llX: " , i * 16 ) ;
2019-09-03 11:58:42 +02:00
for ( j = 0 ; j < 16 ; j + + ) {
2020-04-17 15:14:24 +02:00
DBG ( " %02hhX " , pMBR [ i * 16 + j ] ) ;
2019-09-03 11:58:42 +02:00
}
DBG ( " \n " ) ;
}
2020-10-17 15:01:33 +02:00
Status = SaveBooterLog ( & self . getCloverDir ( ) , LEGBOOT_LOG ) ;
2020-10-03 19:02:31 +02:00
// Jief : don't write outside SelfDir
// if (EFI_ERROR(Status)) {
// Status = SaveBooterLog(NULL, LEGBOOT_LOG);
// }
2019-09-03 11:58:42 +02:00
/*
LogSize = msgCursor - msgbuf ;
2020-10-03 19:02:31 +02:00
Status = egSaveFile ( & self . getSelfRootDir ( ) , LEGBOOT_LOG , ( UINT8 * ) msgbuf , LogSize ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
Status = egSaveFile ( NULL , LEGBOOT_LOG , ( UINT8 * ) msgbuf , LogSize ) ;
}
*/
// Check validity of MBR
if ( pMBR [ 510 ] ! = 0x55 | | pMBR [ 511 ] ! = 0xAA ) {
2020-04-17 15:14:24 +02:00
DBG ( " HDBoot: Invalid MBR signature 0x%02hhX%02hhX (not 0xAA55) \n " , pMBR [ 511 ] , pMBR [ 510 ] ) ;
2019-09-03 11:58:42 +02:00
Status = EFI_NOT_FOUND ;
return Status ;
}
BiosDriveNum = GetBiosDriveNumForVolume ( volume ) ;
if ( BiosDriveNum = = 0 ) {
// not found
DBG ( " HDBoot: BIOS drive number not found \n " ) ;
return EFI_NOT_FOUND ;
}
/*
// Traverse partitions
for ( partitionIndex = 0 ; partitionIndex < 4 ; + + partitionIndex ) {
MBR_PARTITION_INFO * partition = ( MBR_PARTITION_INFO * ) ( pMBR + 0x1BE + sizeof ( MBR_PARTITION_INFO ) * partitionIndex ) ;
// Not the active partition?
if ( partition - > Flags ! = 0x80 )
continue ;
// Is the partition valid?
if ( partition - > StartLBA = = 0 | | partition - > Size = = 0 ) {
2020-04-17 15:14:24 +02:00
DBG ( " HDBoot: Invalid active partition %d: (%08hhX L %08hhX) \n " , partition - > StartLBA , partition - > Size ) ;
2019-09-03 11:58:42 +02:00
return Status ;
}
activePartition = partition ;
break ;
}
// No active partitions found?
if ( ! activePartition ) {
DBG ( " HDBoot: No active partitions found. \n " ) ;
Status = EFI_NOT_FOUND ;
return Status ;
}
DBG ( " HDBoot: Found active partition #%d. \n " , partitionIndex ) ;
// Read the boot sector
Status = pDisk - > ReadBlocks ( pDisk , pDisk - > Media - > MediaId , activePartition - > StartLBA , 512 , pBootSector ) ;
if ( EFI_ERROR ( Status ) ) {
2020-08-25 17:35:19 +02:00
DBG ( " HDBoot: Unable to read partition %d's boot sector: %s \n " , partitionIndex , efiStrError ( Status ) ) ;
2019-09-03 11:58:42 +02:00
Status = EFI_NOT_FOUND ;
return Status ;
}
// Check boot sector
if ( pBootSector [ 0x1FE ] ! = 0x55 | | pBootSector [ 0x1FF ] ! = 0xAA ) {
2020-04-17 15:14:24 +02:00
DBG ( " HDBoot: Invalid Boot Sector signature 0x%02hhX%02hhX (not 0xAA55) \n " , pBootSector [ 0x1FF ] , pBootSector [ 0x1FE ] ) ;
2019-09-03 11:58:42 +02:00
Status = EFI_NOT_FOUND ;
return Status ;
}
DBG ( " HDBoot: Found valid boot sector on partition #%d. Booting... \n " , partitionIndex ) ;
*/
DBG ( " HDBoot: Booting... \n " ) ;
Regs . X . DX = BiosDriveNum ;
//Regs.X.SI = (UINT16)(UINTN)activePartition;
LegacyBiosFarCall86 ( 0 , 0x7c00 , & Regs ) ;
// Success - Should never get here
return EFI_SUCCESS ;
}
EFI_STATUS bootPBRtest ( REFIT_VOLUME * volume )
{
EFI_STATUS Status = EFI_NOT_FOUND ;
EFI_BLOCK_IO * pDisk = volume - > BlockIO ;
UINT8 * pBootSector = ( UINT8 * ) ( UINTN ) 0x7C00 ;
UINT8 * mBootSector ;
MBR_PARTITION_INFO * pMBR = ( MBR_PARTITION_INFO * ) ( UINTN ) 0x7BE ;
UINT32 LbaOffset = 0 ;
UINT32 LbaSize = 0 ;
HARDDRIVE_DEVICE_PATH * HdPath = NULL ;
2020-09-28 17:57:50 +02:00
const EFI_DEVICE_PATH_PROTOCOL * DevicePath = volume - > DevicePath ;
2019-09-03 11:58:42 +02:00
UINT8 BiosDriveNum ;
// UINT16 OldMask;
// UINT16 NewMask;
UINTN i , j ; //for debug dump
UINT8 * ptr ;
// UINT32 MBRCRC32;
//UINTN LogSize;
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE * FadtPointer = NULL ;
EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * Facs = NULL ;
IA32_REGISTER_SET Regs ;
2020-05-01 18:26:28 +02:00
SetMem ( & Regs , sizeof ( Regs ) , 0 ) ;
2019-09-03 11:58:42 +02:00
addrEnablePaging ( 0 ) ;
//
// find the partition device path node
//
while ( ! IsDevicePathEnd ( DevicePath ) ) {
if ( ( DevicePathType ( DevicePath ) = = MEDIA_DEVICE_PATH ) & &
( DevicePathSubType ( DevicePath ) = = MEDIA_HARDDRIVE_DP ) ) {
HdPath = ( HARDDRIVE_DEVICE_PATH * ) DevicePath ;
break ;
}
DevicePath = NextDevicePathNode ( DevicePath ) ;
}
if ( HdPath ! = NULL ) {
2020-08-09 17:55:30 +02:00
DBG ( " boot from partition %ls \n " , FileDevicePathToXStringW ( ( EFI_DEVICE_PATH * ) HdPath ) . wc_str ( ) ) ;
2019-09-03 11:58:42 +02:00
LbaOffset = ( UINT32 ) HdPath - > PartitionStart ;
LbaSize = ( UINT32 ) HdPath - > PartitionSize ;
2020-03-25 19:32:44 +01:00
DBG ( " starting from 0x%X LBA \n " , LbaOffset ) ;
2019-09-03 11:58:42 +02:00
} else {
return Status ;
}
2020-10-03 19:02:31 +02:00
Status = gBS - > LocateProtocol ( & gEfiLegacy8259ProtocolGuid , NULL , ( void * * ) & gLegacy8259 ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
return Status ;
}
DBG ( " gEfiLegacy8259ProtocolGuid found \n " ) ;
2020-10-03 19:02:31 +02:00
Status = gBS - > AllocatePool ( EfiBootServicesData , sizeof ( THUNK_CONTEXT ) , ( void * * ) & mThunkContext ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
Status = InitializeBiosIntCaller ( ) ; //mThunkContext);
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
2019-12-21 01:31:49 +01:00
mBootSector = ( __typeof__ ( mBootSector ) ) AllocateAlignedPages ( 1 , 16 ) ;
2019-09-03 11:58:42 +02:00
Status = pDisk - > ReadBlocks ( pDisk , pDisk - > Media - > MediaId , 0 , 2 * 512 , mBootSector ) ;
CopyMem ( pBootSector , mBootSector , 1024 ) ;
DBG ( " PBR after readDisk: \n " ) ;
for ( i = 0 ; i < 4 ; i + + ) {
2020-03-25 19:32:44 +01:00
DBG ( " %04llX: " , i * 16 ) ;
2019-09-03 11:58:42 +02:00
for ( j = 0 ; j < 16 ; j + + ) {
2020-04-17 15:14:24 +02:00
DBG ( " %02hhX " , pBootSector [ i * 16 + j ] ) ;
2019-09-03 11:58:42 +02:00
}
DBG ( " \n " ) ;
}
DBG ( " Reset disk controller 0x80 \n " ) ;
2020-10-17 15:01:33 +02:00
Status = SaveBooterLog ( & self . getCloverDir ( ) , LEGBOOT_LOG ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
DBG ( " can't save legacy-boot.log \n " ) ;
2020-10-03 19:02:31 +02:00
// Jief : don't write outside SelfDir
// Status = SaveBooterLog(NULL, LEGBOOT_LOG);
2019-09-03 11:58:42 +02:00
}
//after reset we can't save boot log
Regs . H . AH = 0x0D ; // INT 13h AH=00h: Reset floppy disk controller; 0x0D - reset hard disk controller
Regs . H . DL = 0x80 ;
Status = EFI_SUCCESS ;
if ( LegacyBiosInt86 ( 0x13 , & Regs ) ) {
// TRUE = error
Status = EFI_NOT_FOUND ;
DBG ( " reset controller 0x80 error \n " ) ;
// return Status;
}
BiosDriveNum = GetBiosDriveNumForVolume ( volume ) ;
if ( BiosDriveNum = = 0 ) {
// not found
DBG ( " HDBoot: BIOS drive number not found \n " ) ;
// BiosDriveNum = 0x80;
// return EFI_NOT_FOUND;
}
//Now I want to start from VideoTest
ptr = ( UINT8 * ) ( UINTN ) 0x7F00 ;
CopyMem ( ptr , & VideoTest [ 0 ] , 30 ) ;
CopyMem ( pMBR , & tMBR , 16 ) ;
pMBR - > StartLBA = LbaOffset ;
pMBR - > Size = LbaSize ;
FadtPointer = GetFadt ( ) ;
if ( FadtPointer = = NULL ) {
return EFI_NOT_FOUND ;
}
Facs = ( EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * ) ( UINTN ) ( FadtPointer - > FirmwareCtrl ) ;
Facs - > FirmwareWakingVector = 0x7F00 ;
2020-02-16 13:00:20 +01:00
gRT - > ResetSystem ( EfiResetWarm , EFI_SUCCESS , 0 , NULL ) ;
2019-09-03 11:58:42 +02:00
/*
Regs . X . DX = BiosDriveNum ;
Regs . X . SI = 0x07BE ;
//Regs.X.ES = EFI_SEGMENT((UINT32) pBootSector);
//Regs.X.BX = EFI_OFFSET ((UINT32) pBootSector);
LegacyBiosFarCall86 ( 0 , 0x7F00 , & Regs ) ; //0x7c00
*/
//if not success then save legacyboot.log
2020-10-17 15:01:33 +02:00
Status = SaveBooterLog ( & self . getCloverDir ( ) , LEGBOOT_LOG ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
DBG ( " can't save legacy-boot.log \n " ) ;
2020-10-03 19:02:31 +02:00
// Jief : don't write outside SelfDir
// /*Status = */SaveBooterLog(NULL, LEGBOOT_LOG);
2019-09-03 11:58:42 +02:00
}
return EFI_SUCCESS ;
}
/*
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE * FadtPointer = GetFadt ( ) ;
if ( FadtPointer = = NULL ) {
return ;
}
Facs = ( EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * ) ( UINTN ) ( FadtPointer - > FirmwareCtrl ) ;
Facs - > FirmwareWakingVector = 0x7F00 ;
2020-02-16 13:00:20 +01:00
gRT - > ResetSystem ( EfiResetWarm , EFI_SUCCESS , 0 , NULL ) ;
2019-09-03 11:58:42 +02:00
*/
# define EFI_CPU_EFLAGS_IF 0x200
/** For BIOS and some UEFI boots.
* Loads partition boot record ( PBR ) and starts it .
*/
EFI_STATUS bootPBR ( REFIT_VOLUME * volume , BOOLEAN SataReset )
{
EFI_STATUS Status ;
EFI_BLOCK_IO * pDisk = volume - > BlockIO ;
UINT8 * pBootSector = ( UINT8 * ) ( UINTN ) 0x7C00 ;
UINT8 * mBootSector ;
UINT32 LbaOffset = 0 ;
UINT32 LbaSize = 0 ;
HARDDRIVE_DEVICE_PATH * HdPath = NULL ;
2020-09-28 17:57:50 +02:00
const EFI_DEVICE_PATH_PROTOCOL * DevicePath = volume - > DevicePath ;
2019-09-03 11:58:42 +02:00
UINT8 BiosDriveNum ;
//UINT16 OldMask;
//UINT16 NewMask;
UINTN i , j ; //for debug dump
IA32_REGISTER_SET Regs ;
//UINTN LogSize;
EFI_LEGACY_BIOS_PROTOCOL * LegacyBios ;
//UINT16 HddCount;
//HDD_INFO *HddInfo = NULL;
UINT16 BbsCount ;
BBS_TABLE * BbsTable = NULL ;
BBS_TABLE * BbsTableIt = NULL ;
2020-02-17 21:41:09 +01:00
CONST CHAR16 * BbsPriorityTxt ;
CONST CHAR16 * BbsDevTypeTxt ;
2019-09-03 11:58:42 +02:00
MBR_PARTITION_INFO * pMBR = ( MBR_PARTITION_INFO * ) ( UINTN ) 0x11BE ; // typical location boot0 installs it, should be unused otherwise...
//
// get EfiLegacy8259Protocol - mandatory
//
2020-10-03 19:02:31 +02:00
Status = gBS - > LocateProtocol ( & gEfiLegacy8259ProtocolGuid , NULL , ( void * * ) & gLegacy8259 ) ;
2020-08-25 17:35:19 +02:00
DBG ( " EfiLegacy8259ProtocolGuid: %s \n " , efiStrError ( Status ) ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
return Status ;
}
if ( SataReset ) {
IoWrite8 ( 0x3F2 , 0x0C ) ;
}
//
// get EfiLegacyBiosProtocol - optional
//
2020-10-03 19:02:31 +02:00
Status = gBS - > LocateProtocol ( & gEfiLegacyBiosProtocolGuid , NULL , ( void * * ) & LegacyBios ) ;
2020-08-25 17:35:19 +02:00
DBG ( " EfiLegacyBiosProtocolGuid: %s \n " , efiStrError ( Status ) ) ;
2019-09-03 11:58:42 +02:00
if ( ! EFI_ERROR ( Status ) ) {
//
// call PrepareToBootEfi() to init BIOS drives
//
//Status = LegacyBios->GetBbsInfo(LegacyBios, &HddCount, &HddInfo, &BbsCount, &BbsTable);
2020-08-25 17:35:19 +02:00
//DBG("GetBbsInfo = %s, HddCnt=%d, HddInfo=%p, BbsCount=%d, BbsTabl%p\n", efiStrError(Status), HddCount, HddInfo, BbsCount, BbsTable);
2019-09-03 11:58:42 +02:00
Status = LegacyBios - > PrepareToBootEfi ( LegacyBios , & BbsCount , & BbsTable ) ;
2020-10-11 08:06:50 +02:00
DBG ( " PrepareToBootEfi = %s, BbsCount=%d, BbsTabl%llx \n " , efiStrError ( Status ) , BbsCount , ( uintptr_t ) BbsTable ) ;
2019-09-03 11:58:42 +02:00
//PauseForKey(L"continue ...\n");
//
// debug: dump BbsTable
//
BbsTableIt = BbsTable ;
for ( i = 0 ; i < BbsCount ; i + + , BbsTableIt + + ) {
BbsPriorityTxt = L " " ;
switch ( BbsTableIt - > BootPriority ) {
case BBS_DO_NOT_BOOT_FROM :
BbsPriorityTxt = L " NOT " ;
break ;
case BBS_LOWEST_PRIORITY :
BbsPriorityTxt = L " LOW " ;
break ;
case BBS_UNPRIORITIZED_ENTRY :
BbsPriorityTxt = L " UNP " ;
break ;
case BBS_IGNORE_ENTRY :
BbsPriorityTxt = L " IGN " ;
break ;
}
BbsDevTypeTxt = L " - " ;
switch ( BbsTableIt - > DeviceType ) {
case BBS_FLOPPY :
BbsDevTypeTxt = L " FLP " ;
break ;
case BBS_HARDDISK :
BbsDevTypeTxt = L " HDD " ;
break ;
case BBS_CDROM :
BbsDevTypeTxt = L " CDR " ;
break ;
case BBS_PCMCIA :
BbsDevTypeTxt = L " PCM " ;
break ;
case BBS_USB :
BbsDevTypeTxt = L " USB " ;
break ;
case BBS_EMBED_NETWORK :
BbsDevTypeTxt = L " NET " ;
break ;
case BBS_BEV_DEVICE :
BbsDevTypeTxt = L " BEV " ;
break ;
}
2020-04-17 15:14:24 +02:00
DBG ( " %llu: Drv: %hhX P: %hX %ls PCI(%X,%X,%X), DT: %hX %ls SF: %X Txt: '%s' \n " ,
2019-09-03 11:58:42 +02:00
i , BbsTableIt - > AssignedDriveNumber , BbsTableIt - > BootPriority , BbsPriorityTxt ,
BbsTableIt - > Bus , BbsTableIt - > Device , BbsTableIt - > Function ,
2020-03-25 19:32:44 +01:00
BbsTableIt - > DeviceType , BbsDevTypeTxt , * ( UINT32 * ) ( & BbsTableIt - > StatusFlags ) ,
2019-09-03 11:58:42 +02:00
( CHAR8 * ) ( UINTN ) ( ( BbsTableIt - > DescStringSegment < < 4 ) + BbsTableIt - > DescStringOffset )
) ;
}
//PauseForKey(L"continue ...\n");
}
//
// find the partition device path node
//
while ( ! IsDevicePathEnd ( DevicePath ) ) {
if ( ( DevicePathType ( DevicePath ) = = MEDIA_DEVICE_PATH ) & &
( DevicePathSubType ( DevicePath ) = = MEDIA_HARDDRIVE_DP ) ) {
HdPath = ( HARDDRIVE_DEVICE_PATH * ) DevicePath ;
break ;
}
DevicePath = NextDevicePathNode ( DevicePath ) ;
}
if ( HdPath ! = NULL ) {
2020-08-09 17:55:30 +02:00
DBG ( " boot from partition %ls \n " , FileDevicePathToXStringW ( ( EFI_DEVICE_PATH * ) HdPath ) . wc_str ( ) ) ;
2019-09-03 11:58:42 +02:00
LbaOffset = ( UINT32 ) HdPath - > PartitionStart ;
LbaSize = ( UINT32 ) HdPath - > PartitionSize ;
2020-03-25 19:32:44 +01:00
DBG ( " starting from 0x%X LBA \n " , LbaOffset ) ;
2019-09-03 11:58:42 +02:00
} else {
return Status ;
}
//
// prepare ThunkContext for 16bit BIOS calls
//
if ( mThunkContext = = NULL ) {
2020-10-03 19:02:31 +02:00
Status = gBS - > AllocatePool ( EfiBootServicesData , sizeof ( THUNK_CONTEXT ) , ( void * * ) & mThunkContext ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
DBG ( " Thunk allocated \n " ) ;
Status = InitializeBiosIntCaller ( ) ; //mThunkContext);
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
}
//
// read partition boot record and copy it to BIOS boot area 0000:07C00
//
2019-12-21 01:31:49 +01:00
mBootSector = ( __typeof__ ( mBootSector ) ) AllocatePages ( 1 ) ;
2019-09-03 11:58:42 +02:00
Status = pDisk - > ReadBlocks ( pDisk , pDisk - > Media - > MediaId , 0 , 1 * 512 , mBootSector ) ;
CopyMem ( pBootSector , mBootSector , 1 * 512 ) ;
DBG ( " PBR: \n " ) ;
for ( i = 0 ; i < 4 ; i + + ) {
2020-03-25 19:32:44 +01:00
DBG ( " %04llX: " , i * 16 ) ;
2019-09-03 11:58:42 +02:00
for ( j = 0 ; j < 16 ; j + + ) {
2020-04-17 15:14:24 +02:00
DBG ( " %02hhX " , pBootSector [ i * 16 + j ] ) ;
2019-09-03 11:58:42 +02:00
}
DBG ( " \n " ) ;
}
//
// find parent disk volume and it's BIOS drive num
// todo: if we managed to get BbsTable, then we may find
// BIOS drive from there, by matching PCI bus, device, function
//
2020-08-09 17:55:30 +02:00
DBG ( " Looking for parent disk of %ls \n " , FileDevicePathToXStringW ( volume - > DevicePath ) . wc_str ( ) ) ;
2019-09-03 11:58:42 +02:00
BiosDriveNum = 0 ;
2020-02-27 15:34:29 +01:00
for ( i = 0 ; i < Volumes . size ( ) ; i + + ) {
if ( & Volumes [ i ] ! = volume & & Volumes [ i ] . BlockIO = = volume - > WholeDiskBlockIO )
2019-09-03 11:58:42 +02:00
{
2020-02-27 15:34:29 +01:00
BiosDriveNum = GetBiosDriveNumForVolume ( & Volumes [ i ] ) ;
2019-09-03 11:58:42 +02:00
break ;
}
}
if ( BiosDriveNum = = 0 ) {
// not found
DBG ( " HDBoot: BIOS drive number not found, using default 0x80 \n " ) ;
BiosDriveNum = 0x80 ;
}
//
// prepare 16bit regs:
// DX = BIOS drive num
//
2020-05-01 18:26:28 +02:00
SetMem ( & Regs , sizeof ( Regs ) , 0 ) ;
2019-09-03 11:58:42 +02:00
Regs . X . DX = BiosDriveNum ;
// set up SI to partition table entry, some boot1 boot code (such a boot1f32 and boot1h) depend on it
if ( volume - > IsMbrPartition ) {
CopyMem ( pMBR , volume - > MbrPartitionTable , 4 * 16 ) ; // copy to lower memory, same location as boot0
Regs . X . SI = ( UINT16 ) ( UINTN ) & pMBR [ volume - > MbrPartitionIndex ] ;
}
// apparently gpt without mbr, should this be legacy bootable?
// boot0.s fakes an partition entry, so lets do the same...
else {
CopyMem ( pMBR , & tMBR , 16 ) ;
pMBR - > StartLBA = LbaOffset ;
pMBR - > Size = LbaSize ;
Regs . X . SI = ( UINT16 ) ( UINTN ) pMBR ;
}
2021-04-01 10:06:53 +02:00
DBG ( " mbr: %d index: %llX pointer: %llX dx: %hX si: %hX \n " , volume - > IsMbrPartition , volume - > MbrPartitionIndex , ( uintptr_t ) volume - > MbrPartitionTable , Regs . X . DX , Regs . X . SI ) ;
2020-03-25 19:32:44 +01:00
DBG ( " pmbr: %llX start: %X size: %X \n " , ( uintptr_t ) & pMBR [ volume - > MbrPartitionIndex ] , pMBR [ volume - > MbrPartitionIndex ] . StartLBA , pMBR [ volume - > MbrPartitionIndex ] . Size ) ;
2019-09-03 11:58:42 +02:00
//
// call 16bit partition boot code
//
//PauseForKey(L"Doing LegacyBiosFarCall86 ...\n");
LegacyBiosFarCall86 ( 0 , 0x7c00 , & Regs ) ;
//Status = gLegacy8259->SetMask(gLegacy8259, &OldMask, NULL, NULL, NULL);
2021-05-04 12:03:40 +02:00
PauseForKey ( " save legacy-boot.log ... " _XS8 ) ;
2020-10-17 15:01:33 +02:00
Status = SaveBooterLog ( & self . getCloverDir ( ) , LEGBOOT_LOG ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
DBG ( " can't save legacy-boot.log \n " ) ;
2020-10-03 19:02:31 +02:00
// Jief : don't write outside SelfDir
// /*Status = */SaveBooterLog(NULL, LEGBOOT_LOG);
2019-09-03 11:58:42 +02:00
}
return EFI_SUCCESS ;
}
/** For DefaultLegacyBios (UEFI)
* Patch BBS Table priorities to allow booting not only from first partition .
*/
2020-10-03 19:02:31 +02:00
static void PatchBbsTable ( EFI_LEGACY_BIOS_PROTOCOL * LegacyBios , UINT16 BootEntry )
2019-09-03 11:58:42 +02:00
{
UINT16 Idx ;
UINT16 IdxCount = 0 ;
UINT16 Priority = 1 ;
UINT16 OldPriority ;
UINT16 HddCount ;
UINT16 BbsCount ;
HDD_INFO * LocalHddInfo ;
BBS_TABLE * LocalBbsTable ;
LegacyBios - > GetBbsInfo (
LegacyBios ,
& HddCount ,
& LocalHddInfo ,
& BbsCount ,
& LocalBbsTable
) ;
2020-04-23 18:05:21 +02:00
DBG ( " BBS Table of size %d, patching priorities Pold->Pnew: \n " , BbsCount ) ;
DBG ( " NO: BBS# Pold Pnew bb/dd/ff cl/sc Type Stat segm:offs \n " ) ;
DBG ( " ===================================================== \n " ) ;
2019-09-03 11:58:42 +02:00
for ( Idx = 0 ; Idx < BbsCount ; Idx + + ) {
if ( ( LocalBbsTable [ Idx ] . BootPriority = = BBS_IGNORE_ENTRY ) | |
( LocalBbsTable [ Idx ] . BootPriority = = BBS_DO_NOT_BOOT_FROM ) | |
( LocalBbsTable [ Idx ] . BootPriority = = BBS_LOWEST_PRIORITY )
) {
continue ;
}
OldPriority = LocalBbsTable [ Idx ] . BootPriority ;
if ( + + IdxCount = = BootEntry ) {
LocalBbsTable [ Idx ] . BootPriority = 0 ;
} else {
LocalBbsTable [ Idx ] . BootPriority = Priority + + ;
}
2020-04-23 18:05:21 +02:00
DBG ( " %02llu: 0x%02llX %04llX %04llX %02llX/%02llX/%02llX %02llX/%02llX %04llX %04llX %04llX:%04llX \n " ,
2019-09-03 11:58:42 +02:00
( UINTN ) IdxCount ,
( UINTN ) Idx ,
( UINTN ) OldPriority ,
( UINTN ) LocalBbsTable [ Idx ] . BootPriority ,
( UINTN ) LocalBbsTable [ Idx ] . Bus ,
( UINTN ) LocalBbsTable [ Idx ] . Device ,
( UINTN ) LocalBbsTable [ Idx ] . Function ,
( UINTN ) LocalBbsTable [ Idx ] . Class ,
( UINTN ) LocalBbsTable [ Idx ] . SubClass ,
( UINTN ) LocalBbsTable [ Idx ] . DeviceType ,
( UINTN ) * ( UINT16 * ) & LocalBbsTable [ Idx ] . StatusFlags ,
( UINTN ) LocalBbsTable [ Idx ] . BootHandlerSegment ,
2020-03-25 19:32:44 +01:00
( UINTN ) LocalBbsTable [ Idx ] . BootHandlerOffset /*,
2019-09-03 11:58:42 +02:00
( UINTN ) ( ( LocalBbsTable [ Idx ] . MfgStringSegment < < 4 ) + LocalBbsTable [ Idx ] . MfgStringOffset ) ,
2020-03-25 19:32:44 +01:00
( UINTN ) ( ( LocalBbsTable [ Idx ] . DescStringSegment < < 4 ) + LocalBbsTable [ Idx ] . DescStringOffset ) */
2019-09-03 11:58:42 +02:00
) ;
}
}
/** For some UEFI boots that have EfiLegacyBiosProtocol.
* Starts legacy boot from the first BIOS drive .
*/
EFI_STATUS bootLegacyBiosDefault ( IN UINT16 LegacyBiosDefaultEntry )
{
EFI_STATUS Status ;
EFI_LEGACY_BIOS_PROTOCOL * LegacyBios ;
//BBS_BBS_DEVICE_PATH *BbsDPN;
BBS_BBS_DEVICE_PATH * BbsDP = NULL ;
//
// get EfiLegacyBiosProtocol - optional
//
2020-10-03 19:02:31 +02:00
Status = gBS - > LocateProtocol ( & gEfiLegacyBiosProtocolGuid , NULL , ( void * * ) & LegacyBios ) ;
2020-08-25 17:35:19 +02:00
DBG ( " EfiLegacyBiosProtocolGuid: %s \n " , efiStrError ( Status ) ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
return Status ;
}
// Patch BBS Table
if ( LegacyBiosDefaultEntry > 0 ) {
PatchBbsTable ( LegacyBios , LegacyBiosDefaultEntry ) ;
2020-10-03 19:02:31 +02:00
/*Status = SaveBooterLog(&self.getSelfRootDir(), LEGBOOT_LOG);
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
DBG ( " can't save legacy-boot.log \n " ) ;
Status = SaveBooterLog ( NULL , LEGBOOT_LOG ) ;
} */
}
/* commented out - it seems it does not have any effect
//
// create BBS device path for HDD
//
// size - size of struct, no additional String
BbsDPN = ( BBS_BBS_DEVICE_PATH * ) CreateDeviceNode ( BBS_DEVICE_PATH , BBS_BBS_DP , sizeof ( BBS_BBS_DEVICE_PATH ) ) ;
BbsDPN - > DeviceType = BBS_TYPE_HARDDRIVE ; // BBS_TYPE_CDROM;
BbsDPN - > StatusFlag = 0 ;
2020-08-25 17:35:19 +02:00
BbsDPN - > getString ( ) - > stringValue ( ) [ 0 ] = ' \0 ' ;
2019-09-03 11:58:42 +02:00
// appends end-of-device-path node and returns complete DP
BbsDP = ( BBS_BBS_DEVICE_PATH * ) AppendDevicePathNode ( NULL , ( EFI_DEVICE_PATH_PROTOCOL * ) BbsDPN ) ;
FreePool ( BbsDPN ) ;
*/
//
// do boot from default MBR hard disk
//
Status = LegacyBios - > LegacyBoot ( LegacyBios , BbsDP , 0 , NULL ) ;
2020-08-25 17:35:19 +02:00
DBG ( " LegacyBios->LegacyBoot(): %s \n " , efiStrError ( Status ) ) ;
2019-09-03 11:58:42 +02:00
return Status ;
}
2020-10-03 19:02:31 +02:00
void DumpBiosMemoryMap ( )
2019-09-03 11:58:42 +02:00
{
EFI_STATUS Status ;
INT32 i , Length ; //for debug dump
UINT64 Start , Size ;
IA32_REGISTER_SET Regs ;
UINT8 * BiosMap = ( UINT8 * ) ( UINTN ) 0x7C00 ;
2020-05-01 18:26:28 +02:00
SetMem ( & Regs , sizeof ( Regs ) , 0 ) ;
2019-09-03 11:58:42 +02:00
addrEnablePaging ( 0 ) ;
2020-10-03 19:02:31 +02:00
Status = gBS - > LocateProtocol ( & gEfiLegacy8259ProtocolGuid , NULL , ( void * * ) & gLegacy8259 ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) ) {
return ;
}
DBG ( " gEfiLegacy8259ProtocolGuid found \n " ) ;
2020-10-03 19:02:31 +02:00
Status = gBS - > AllocatePool ( EfiBootServicesData , sizeof ( THUNK_CONTEXT ) , ( void * * ) & mThunkContext ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return ;
}
Status = InitializeBiosIntCaller ( ) ; //mThunkContext);
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return ;
}
Regs . E . EBX = 0 ;
Regs . E . EDI = 0x7C00 ;
do {
Regs . X . AX = 0xE820 ;
Regs . E . EDX = 0x534d4150 ;
Regs . X . CX = 24 ;
if ( LegacyBiosInt86 ( 0x15 , & Regs ) ) {
DBG ( " finished by bit C \n " ) ;
break ;
}
if ( Regs . E . EBX = = 0 ) {
DBG ( " finished by ebx=0 \n " ) ;
break ;
}
Regs . E . EDI + = 24 ;
} while ( Regs . E . EDI < 0x8000 ) ;
Length = ( ( INT32 ) ( Regs . E . EDI - 0x7c00 ) ) / 24 + 1 ;
DBG ( " BiosMemoryMap length=%d: \n Start End Type Ext \n " , Length ) ;
for ( i = 0 ; i < Length ; i + + ) {
Start = * ( UINT64 * ) BiosMap ;
Size = * ( ( UINT64 * ) BiosMap + 1 ) ;
2020-03-25 19:32:44 +01:00
DBG ( " %08llx %08llx %X %08X \n " , Start , Start + Size - 1 , * ( UINT32 * ) ( BiosMap + 16 ) , * ( UINT32 * ) ( BiosMap + 20 ) ) ;
2019-09-03 11:58:42 +02:00
BiosMap + = 24 ;
}
}