1bcecde140a561c64e297225904afebebd62336cejljusten/** @file 2bcecde140a561c64e297225904afebebd62336cejljusten Call into 16-bit BIOS code 3bcecde140a561c64e297225904afebebd62336cejljusten 4bcecde140a561c64e297225904afebebd62336cejljusten BugBug: Thunker does A20 gate. Can we get rid of this code or 5bcecde140a561c64e297225904afebebd62336cejljusten put it into Legacy16 code. 6bcecde140a561c64e297225904afebebd62336cejljusten 71a45b15eae48d9bf498daf5b0c0771659d75faa2Jeff FanCopyright (c) 1999 - 2014, Intel Corporation. All rights reserved.<BR> 8bcecde140a561c64e297225904afebebd62336cejljusten 9bcecde140a561c64e297225904afebebd62336cejljustenThis program and the accompanying materials 10bcecde140a561c64e297225904afebebd62336cejljustenare licensed and made available under the terms and conditions 11bcecde140a561c64e297225904afebebd62336cejljustenof the BSD License which accompanies this distribution. The 12bcecde140a561c64e297225904afebebd62336cejljustenfull text of the license may be found at 13bcecde140a561c64e297225904afebebd62336cejljustenhttp://opensource.org/licenses/bsd-license.php 14bcecde140a561c64e297225904afebebd62336cejljusten 15bcecde140a561c64e297225904afebebd62336cejljustenTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 16bcecde140a561c64e297225904afebebd62336cejljustenWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 17bcecde140a561c64e297225904afebebd62336cejljusten 18bcecde140a561c64e297225904afebebd62336cejljusten**/ 19bcecde140a561c64e297225904afebebd62336cejljusten 20bcecde140a561c64e297225904afebebd62336cejljusten#include "LegacyBiosInterface.h" 21bcecde140a561c64e297225904afebebd62336cejljusten#include "IpfThunk.h" 22bcecde140a561c64e297225904afebebd62336cejljusten 23bcecde140a561c64e297225904afebebd62336cejljusten/** 24bcecde140a561c64e297225904afebebd62336cejljusten Gets the current flat GDT and IDT descriptors and store them in 25bcecde140a561c64e297225904afebebd62336cejljusten Private->IntThunk. These values are used by the Thunk code. 26bcecde140a561c64e297225904afebebd62336cejljusten This method must be called before every thunk in order to assure 27bcecde140a561c64e297225904afebebd62336cejljusten that the correct GDT and IDT are restored after the thunk. 28bcecde140a561c64e297225904afebebd62336cejljusten 29bcecde140a561c64e297225904afebebd62336cejljusten @param Private Private context for Legacy BIOS 30bcecde140a561c64e297225904afebebd62336cejljusten 31bcecde140a561c64e297225904afebebd62336cejljusten @retval EFI_SUCCESS Should only pass. 32bcecde140a561c64e297225904afebebd62336cejljusten 33bcecde140a561c64e297225904afebebd62336cejljusten**/ 34bcecde140a561c64e297225904afebebd62336cejljustenEFI_STATUS 35bcecde140a561c64e297225904afebebd62336cejljustenLegacyBiosGetFlatDescs ( 36bcecde140a561c64e297225904afebebd62336cejljusten IN LEGACY_BIOS_INSTANCE *Private 37bcecde140a561c64e297225904afebebd62336cejljusten ) 38bcecde140a561c64e297225904afebebd62336cejljusten{ 39bcecde140a561c64e297225904afebebd62336cejljusten return EFI_SUCCESS; 40bcecde140a561c64e297225904afebebd62336cejljusten} 41bcecde140a561c64e297225904afebebd62336cejljusten 42bcecde140a561c64e297225904afebebd62336cejljusten 43bcecde140a561c64e297225904afebebd62336cejljusten/** 44bcecde140a561c64e297225904afebebd62336cejljusten BIOS interrupt call function. 45bcecde140a561c64e297225904afebebd62336cejljusten 46bcecde140a561c64e297225904afebebd62336cejljusten @param BiosInt Int number of BIOS call 47bcecde140a561c64e297225904afebebd62336cejljusten @param Segment Segment number 48bcecde140a561c64e297225904afebebd62336cejljusten @param Offset Offset in segment 49bcecde140a561c64e297225904afebebd62336cejljusten @param Regs IA32 Register set. 50bcecde140a561c64e297225904afebebd62336cejljusten @param Stack Base address of stack 51bcecde140a561c64e297225904afebebd62336cejljusten @param StackSize Size of stack 52bcecde140a561c64e297225904afebebd62336cejljusten 53bcecde140a561c64e297225904afebebd62336cejljusten @retval EFI_SUCCESS BIOS interrupt call succeeds. 54bcecde140a561c64e297225904afebebd62336cejljusten 55bcecde140a561c64e297225904afebebd62336cejljusten**/ 56bcecde140a561c64e297225904afebebd62336cejljustenEFI_STATUS 57bcecde140a561c64e297225904afebebd62336cejljustenBiosIntCall ( 58bcecde140a561c64e297225904afebebd62336cejljusten IN UINT16 BiosInt, 59bcecde140a561c64e297225904afebebd62336cejljusten IN UINT16 Segment, 60bcecde140a561c64e297225904afebebd62336cejljusten IN UINT16 Offset, 61bcecde140a561c64e297225904afebebd62336cejljusten IN EFI_IA32_REGISTER_SET *Regs, 62bcecde140a561c64e297225904afebebd62336cejljusten IN VOID *Stack, 63bcecde140a561c64e297225904afebebd62336cejljusten IN UINTN StackSize 64bcecde140a561c64e297225904afebebd62336cejljusten ) 65bcecde140a561c64e297225904afebebd62336cejljusten{ 66bcecde140a561c64e297225904afebebd62336cejljusten IPF_DWORD_REGS DwordRegs; 67bcecde140a561c64e297225904afebebd62336cejljusten UINT64 IntTypeVariable; 68bcecde140a561c64e297225904afebebd62336cejljusten 69bcecde140a561c64e297225904afebebd62336cejljusten IntTypeVariable = 0x8000000000000000; 701a45b15eae48d9bf498daf5b0c0771659d75faa2Jeff Fan IntTypeVariable |= (UINT64)BiosInt; 71bcecde140a561c64e297225904afebebd62336cejljusten 72bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Cs = Segment; 73bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Eip = Offset; 74bcecde140a561c64e297225904afebebd62336cejljusten 75bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Ds = Regs->X.DS; 76bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Es = Regs->X.ES; 77bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Fs = Regs->X.ES; 78bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Gs = Regs->X.ES; 79bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Ss = 0xFFFF; 80bcecde140a561c64e297225904afebebd62336cejljusten 81bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Eax = Regs->X.AX; 82bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Ebx = Regs->X.BX; 83bcecde140a561c64e297225904afebebd62336cejljusten // 84bcecde140a561c64e297225904afebebd62336cejljusten // Sometimes, ECX is used to pass in 32 bit data. For example, INT 1Ah, AX = B10Dh is 85bcecde140a561c64e297225904afebebd62336cejljusten // "PCI BIOS v2.0c + Write Configuration DWORD" and ECX has the dword to write. 86bcecde140a561c64e297225904afebebd62336cejljusten // 87bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Ecx = Regs->E.ECX; 88bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Edx = Regs->X.DX; 89bcecde140a561c64e297225904afebebd62336cejljusten 90bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Ebp = Regs->X.BP; 91bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Eflag = *((UINT16 *) &Regs->X.Flags); 92bcecde140a561c64e297225904afebebd62336cejljusten 93bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Edi = Regs->X.DI; 94bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Esi = Regs->X.SI; 95bcecde140a561c64e297225904afebebd62336cejljusten DwordRegs.Esp = 0xFFFFFFFF; 96bcecde140a561c64e297225904afebebd62336cejljusten 97bcecde140a561c64e297225904afebebd62336cejljusten EfiIaEntryPoint (IntTypeVariable, &DwordRegs, ((UINTN) Stack + StackSize), StackSize); 98bcecde140a561c64e297225904afebebd62336cejljusten 99bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.CS = DwordRegs.Cs; 100bcecde140a561c64e297225904afebebd62336cejljusten 101bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.DS = (UINT16) DwordRegs.Ds; 102bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.SS = (UINT16) DwordRegs.Ss; 103bcecde140a561c64e297225904afebebd62336cejljusten 104bcecde140a561c64e297225904afebebd62336cejljusten Regs->E.EAX = DwordRegs.Eax; 105bcecde140a561c64e297225904afebebd62336cejljusten Regs->E.EBX = DwordRegs.Ebx; 106bcecde140a561c64e297225904afebebd62336cejljusten Regs->E.ECX = DwordRegs.Ecx; 107bcecde140a561c64e297225904afebebd62336cejljusten Regs->E.EDX = DwordRegs.Edx; 108bcecde140a561c64e297225904afebebd62336cejljusten 109bcecde140a561c64e297225904afebebd62336cejljusten Regs->E.EBP = DwordRegs.Ebp; 110bcecde140a561c64e297225904afebebd62336cejljusten CopyMem (&Regs->X.Flags, &DwordRegs.Eflag, sizeof (EFI_FLAGS_REG)); 111bcecde140a561c64e297225904afebebd62336cejljusten 112bcecde140a561c64e297225904afebebd62336cejljusten Regs->E.EDI = DwordRegs.Edi; 113bcecde140a561c64e297225904afebebd62336cejljusten Regs->E.ESI = DwordRegs.Esi; 114bcecde140a561c64e297225904afebebd62336cejljusten 115bcecde140a561c64e297225904afebebd62336cejljusten return EFI_SUCCESS; 116bcecde140a561c64e297225904afebebd62336cejljusten} 117bcecde140a561c64e297225904afebebd62336cejljusten 118bcecde140a561c64e297225904afebebd62336cejljusten 119bcecde140a561c64e297225904afebebd62336cejljusten/** 120bcecde140a561c64e297225904afebebd62336cejljusten Template of real mode code. 121bcecde140a561c64e297225904afebebd62336cejljusten 122bcecde140a561c64e297225904afebebd62336cejljusten @param CodeStart Start address of code. 123bcecde140a561c64e297225904afebebd62336cejljusten @param CodeEnd End address of code 124bcecde140a561c64e297225904afebebd62336cejljusten @param ReverseThunkStart Start of reverse thunk. 125bcecde140a561c64e297225904afebebd62336cejljusten @param IntThunk Low memory thunk. 126bcecde140a561c64e297225904afebebd62336cejljusten 127bcecde140a561c64e297225904afebebd62336cejljusten**/ 128bcecde140a561c64e297225904afebebd62336cejljustenVOID 129bcecde140a561c64e297225904afebebd62336cejljustenRealModeTemplate ( 130bcecde140a561c64e297225904afebebd62336cejljusten OUT UINTN *CodeStart, 131bcecde140a561c64e297225904afebebd62336cejljusten OUT UINTN *CodeEnd, 132bcecde140a561c64e297225904afebebd62336cejljusten OUT UINTN *ReverseThunkStart, 133bcecde140a561c64e297225904afebebd62336cejljusten LOW_MEMORY_THUNK *IntThunk 134bcecde140a561c64e297225904afebebd62336cejljusten ) 135bcecde140a561c64e297225904afebebd62336cejljusten{ 136bcecde140a561c64e297225904afebebd62336cejljusten SAL_RETURN_REGS SalStatus; 137bcecde140a561c64e297225904afebebd62336cejljusten 138bcecde140a561c64e297225904afebebd62336cejljusten SalStatus = EsalGetReverseThunkAddress (); 139bcecde140a561c64e297225904afebebd62336cejljusten 140bcecde140a561c64e297225904afebebd62336cejljusten *CodeStart = SalStatus.r9; 141bcecde140a561c64e297225904afebebd62336cejljusten *CodeEnd = SalStatus.r10; 142bcecde140a561c64e297225904afebebd62336cejljusten *ReverseThunkStart = SalStatus.r11; 143bcecde140a561c64e297225904afebebd62336cejljusten 144bcecde140a561c64e297225904afebebd62336cejljusten} 145bcecde140a561c64e297225904afebebd62336cejljusten 146bcecde140a561c64e297225904afebebd62336cejljusten 147bcecde140a561c64e297225904afebebd62336cejljusten/** 148bcecde140a561c64e297225904afebebd62336cejljusten Allocate memory < 1 MB and copy the thunker code into low memory. Se up 149bcecde140a561c64e297225904afebebd62336cejljusten all the descriptors. 150bcecde140a561c64e297225904afebebd62336cejljusten 151bcecde140a561c64e297225904afebebd62336cejljusten @param Private Private context for Legacy BIOS 152bcecde140a561c64e297225904afebebd62336cejljusten 153bcecde140a561c64e297225904afebebd62336cejljusten @retval EFI_SUCCESS Should only pass. 154bcecde140a561c64e297225904afebebd62336cejljusten 155bcecde140a561c64e297225904afebebd62336cejljusten**/ 156bcecde140a561c64e297225904afebebd62336cejljustenEFI_STATUS 157bcecde140a561c64e297225904afebebd62336cejljustenLegacyBiosInitializeThunk ( 158bcecde140a561c64e297225904afebebd62336cejljusten IN LEGACY_BIOS_INSTANCE *Private 159bcecde140a561c64e297225904afebebd62336cejljusten ) 160bcecde140a561c64e297225904afebebd62336cejljusten{ 161bcecde140a561c64e297225904afebebd62336cejljusten GDT32 *CodeGdt; 162bcecde140a561c64e297225904afebebd62336cejljusten GDT32 *DataGdt; 163bcecde140a561c64e297225904afebebd62336cejljusten UINTN CodeStart; 164bcecde140a561c64e297225904afebebd62336cejljusten UINTN CodeEnd; 165bcecde140a561c64e297225904afebebd62336cejljusten UINTN ReverseThunkStart; 166bcecde140a561c64e297225904afebebd62336cejljusten UINT32 Base; 167bcecde140a561c64e297225904afebebd62336cejljusten LOW_MEMORY_THUNK *IntThunk; 168bcecde140a561c64e297225904afebebd62336cejljusten UINTN TempData; 169bcecde140a561c64e297225904afebebd62336cejljusten 170bcecde140a561c64e297225904afebebd62336cejljusten ASSERT (Private); 171bcecde140a561c64e297225904afebebd62336cejljusten 172bcecde140a561c64e297225904afebebd62336cejljusten IntThunk = Private->IntThunk; 173bcecde140a561c64e297225904afebebd62336cejljusten 174bcecde140a561c64e297225904afebebd62336cejljusten // 175bcecde140a561c64e297225904afebebd62336cejljusten // Clear the reserved descriptor 176bcecde140a561c64e297225904afebebd62336cejljusten // 177bcecde140a561c64e297225904afebebd62336cejljusten ZeroMem (&(IntThunk->RealModeGdt[0]), sizeof (GDT32)); 178bcecde140a561c64e297225904afebebd62336cejljusten 179bcecde140a561c64e297225904afebebd62336cejljusten // 180bcecde140a561c64e297225904afebebd62336cejljusten // Setup a descriptor for real-mode code 181bcecde140a561c64e297225904afebebd62336cejljusten // 182bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt = &(IntThunk->RealModeGdt[1]); 183bcecde140a561c64e297225904afebebd62336cejljusten 184bcecde140a561c64e297225904afebebd62336cejljusten // 185bcecde140a561c64e297225904afebebd62336cejljusten // Fill in the descriptor with our real-mode segment value 186bcecde140a561c64e297225904afebebd62336cejljusten // 187bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt->Type = 0xA; 188bcecde140a561c64e297225904afebebd62336cejljusten // 189bcecde140a561c64e297225904afebebd62336cejljusten // code/read 190bcecde140a561c64e297225904afebebd62336cejljusten // 191bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt->System = 1; 192bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt->Dpl = 0; 193bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt->Present = 1; 194bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt->Software = 0; 195bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt->Reserved = 0; 196bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt->DefaultSize = 0; 197bcecde140a561c64e297225904afebebd62336cejljusten // 198bcecde140a561c64e297225904afebebd62336cejljusten // 16 bit operands 199bcecde140a561c64e297225904afebebd62336cejljusten // 200bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt->Granularity = 0; 201bcecde140a561c64e297225904afebebd62336cejljusten 202bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt->LimitHi = 0; 203bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt->LimitLo = 0xffff; 204bcecde140a561c64e297225904afebebd62336cejljusten 205bcecde140a561c64e297225904afebebd62336cejljusten Base = (*((UINT32 *) &IntThunk->Code)); 206bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt->BaseHi = (Base >> 24) & 0xFF; 207bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt->BaseMid = (Base >> 16) & 0xFF; 208bcecde140a561c64e297225904afebebd62336cejljusten CodeGdt->BaseLo = Base & 0xFFFF; 209bcecde140a561c64e297225904afebebd62336cejljusten 210bcecde140a561c64e297225904afebebd62336cejljusten // 211bcecde140a561c64e297225904afebebd62336cejljusten // Setup a descriptor for read-mode data 212bcecde140a561c64e297225904afebebd62336cejljusten // 213bcecde140a561c64e297225904afebebd62336cejljusten DataGdt = &(IntThunk->RealModeGdt[2]); 214bcecde140a561c64e297225904afebebd62336cejljusten CopyMem (DataGdt, CodeGdt, sizeof (GDT32)); 215bcecde140a561c64e297225904afebebd62336cejljusten 216bcecde140a561c64e297225904afebebd62336cejljusten DataGdt->Type = 0x2; 217bcecde140a561c64e297225904afebebd62336cejljusten // 218bcecde140a561c64e297225904afebebd62336cejljusten // read/write data 219bcecde140a561c64e297225904afebebd62336cejljusten // 220bcecde140a561c64e297225904afebebd62336cejljusten DataGdt->BaseHi = 0x0; 221bcecde140a561c64e297225904afebebd62336cejljusten // 222bcecde140a561c64e297225904afebebd62336cejljusten // Base = 0 223bcecde140a561c64e297225904afebebd62336cejljusten // 224bcecde140a561c64e297225904afebebd62336cejljusten DataGdt->BaseMid = 0x0; 225bcecde140a561c64e297225904afebebd62336cejljusten // 226bcecde140a561c64e297225904afebebd62336cejljusten DataGdt->BaseLo = 0x0; 227bcecde140a561c64e297225904afebebd62336cejljusten // 228bcecde140a561c64e297225904afebebd62336cejljusten DataGdt->LimitHi = 0x0F; 229bcecde140a561c64e297225904afebebd62336cejljusten // 230bcecde140a561c64e297225904afebebd62336cejljusten // Limit = 4Gb 231bcecde140a561c64e297225904afebebd62336cejljusten // 232bcecde140a561c64e297225904afebebd62336cejljusten DataGdt->LimitLo = 0xFFFF; 233bcecde140a561c64e297225904afebebd62336cejljusten // 234bcecde140a561c64e297225904afebebd62336cejljusten DataGdt->Granularity = 0x1; 235bcecde140a561c64e297225904afebebd62336cejljusten // 236bcecde140a561c64e297225904afebebd62336cejljusten // 237bcecde140a561c64e297225904afebebd62336cejljusten // Compute selector value 238bcecde140a561c64e297225904afebebd62336cejljusten // 239bcecde140a561c64e297225904afebebd62336cejljusten IntThunk->RealModeGdtDesc.Limit = (UINT16) (sizeof (IntThunk->RealModeGdt) - 1); 240bcecde140a561c64e297225904afebebd62336cejljusten CopyMem (&IntThunk->RealModeGdtDesc.Base, (UINT32 *) &IntThunk->RealModeGdt, sizeof (UINT32)); 241bcecde140a561c64e297225904afebebd62336cejljusten // 242bcecde140a561c64e297225904afebebd62336cejljusten // IntThunk->RealModeGdtDesc.Base = *((UINT32*) &IntThunk->RealModeGdt); 243bcecde140a561c64e297225904afebebd62336cejljusten // 244bcecde140a561c64e297225904afebebd62336cejljusten IntThunk->RealModeIdtDesc.Limit = 0xFFFF; 245bcecde140a561c64e297225904afebebd62336cejljusten IntThunk->RealModeIdtDesc.Base = 0; 246bcecde140a561c64e297225904afebebd62336cejljusten IntThunk->LowCodeSelector = (UINT32) ((UINTN) CodeGdt - IntThunk->RealModeGdtDesc.Base); 247bcecde140a561c64e297225904afebebd62336cejljusten IntThunk->LowDataSelector = (UINT32) ((UINTN) DataGdt - IntThunk->RealModeGdtDesc.Base); 248bcecde140a561c64e297225904afebebd62336cejljusten 249bcecde140a561c64e297225904afebebd62336cejljusten // 250bcecde140a561c64e297225904afebebd62336cejljusten // Initialize low real-mode code thunk 251bcecde140a561c64e297225904afebebd62336cejljusten // 252bcecde140a561c64e297225904afebebd62336cejljusten RealModeTemplate (&CodeStart, &CodeEnd, &ReverseThunkStart, IntThunk); 253bcecde140a561c64e297225904afebebd62336cejljusten 254bcecde140a561c64e297225904afebebd62336cejljusten TempData = (UINTN) &(IntThunk->Code); 255bcecde140a561c64e297225904afebebd62336cejljusten IntThunk->LowReverseThunkStart = ((UINT32) TempData + (UINT32) (ReverseThunkStart - CodeStart)); 256bcecde140a561c64e297225904afebebd62336cejljusten 257bcecde140a561c64e297225904afebebd62336cejljusten EsalSetSalDataArea (TempData, (UINTN) IntThunk); 258bcecde140a561c64e297225904afebebd62336cejljusten CopyMem (IntThunk->Code, (VOID *) CodeStart, CodeEnd - CodeStart); 259bcecde140a561c64e297225904afebebd62336cejljusten 260bcecde140a561c64e297225904afebebd62336cejljusten IntThunk->EfiToLegacy16InitTable.ReverseThunkCallSegment = EFI_SEGMENT (*((UINT32 *) &IntThunk->LowReverseThunkStart)); 261bcecde140a561c64e297225904afebebd62336cejljusten IntThunk->EfiToLegacy16InitTable.ReverseThunkCallOffset = EFI_OFFSET (*((UINT32 *) &IntThunk->LowReverseThunkStart)); 262bcecde140a561c64e297225904afebebd62336cejljusten 263bcecde140a561c64e297225904afebebd62336cejljusten return EFI_SUCCESS; 264bcecde140a561c64e297225904afebebd62336cejljusten} 265bcecde140a561c64e297225904afebebd62336cejljusten 266bcecde140a561c64e297225904afebebd62336cejljusten 267bcecde140a561c64e297225904afebebd62336cejljusten/** 268bcecde140a561c64e297225904afebebd62336cejljusten Thunk to 16-bit real mode and execute a software interrupt with a vector 269bcecde140a561c64e297225904afebebd62336cejljusten of BiosInt. Regs will contain the 16-bit register context on entry and 270bcecde140a561c64e297225904afebebd62336cejljusten exit. 271bcecde140a561c64e297225904afebebd62336cejljusten 272bcecde140a561c64e297225904afebebd62336cejljusten @param This Protocol instance pointer. 273bcecde140a561c64e297225904afebebd62336cejljusten @param BiosInt Processor interrupt vector to invoke 274bcecde140a561c64e297225904afebebd62336cejljusten @param Regs Register contexted passed into (and returned) from 275bcecde140a561c64e297225904afebebd62336cejljusten thunk to 16-bit mode 276bcecde140a561c64e297225904afebebd62336cejljusten 277bcecde140a561c64e297225904afebebd62336cejljusten @retval FALSE Thunk completed, and there were no BIOS errors in the 278bcecde140a561c64e297225904afebebd62336cejljusten target code. See Regs for status. 279bcecde140a561c64e297225904afebebd62336cejljusten @retval TRUE There was a BIOS erro in the target code. 280bcecde140a561c64e297225904afebebd62336cejljusten 281bcecde140a561c64e297225904afebebd62336cejljusten**/ 282bcecde140a561c64e297225904afebebd62336cejljustenBOOLEAN 283bcecde140a561c64e297225904afebebd62336cejljustenEFIAPI 284bcecde140a561c64e297225904afebebd62336cejljustenLegacyBiosInt86 ( 285bcecde140a561c64e297225904afebebd62336cejljusten IN EFI_LEGACY_BIOS_PROTOCOL *This, 286bcecde140a561c64e297225904afebebd62336cejljusten IN UINT8 BiosInt, 287bcecde140a561c64e297225904afebebd62336cejljusten IN EFI_IA32_REGISTER_SET *Regs 288bcecde140a561c64e297225904afebebd62336cejljusten ) 289bcecde140a561c64e297225904afebebd62336cejljusten{ 290bcecde140a561c64e297225904afebebd62336cejljusten EFI_STATUS Status; 291bcecde140a561c64e297225904afebebd62336cejljusten LEGACY_BIOS_INSTANCE *Private; 292bcecde140a561c64e297225904afebebd62336cejljusten LOW_MEMORY_THUNK *IntThunk; 293bcecde140a561c64e297225904afebebd62336cejljusten UINT16 *Stack16; 294bcecde140a561c64e297225904afebebd62336cejljusten EFI_TPL OriginalTpl; 295bcecde140a561c64e297225904afebebd62336cejljusten UINTN IaSegment; 296bcecde140a561c64e297225904afebebd62336cejljusten UINTN IaOffset; 297bcecde140a561c64e297225904afebebd62336cejljusten UINTN *Address; 298bcecde140a561c64e297225904afebebd62336cejljusten UINTN TempData; 299bcecde140a561c64e297225904afebebd62336cejljusten 300bcecde140a561c64e297225904afebebd62336cejljusten Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); 301bcecde140a561c64e297225904afebebd62336cejljusten IntThunk = Private->IntThunk; 302bcecde140a561c64e297225904afebebd62336cejljusten 303bcecde140a561c64e297225904afebebd62336cejljusten // 304bcecde140a561c64e297225904afebebd62336cejljusten // Get the current flat GDT, IDT, and SS and store them in Private->IntThunk. 305bcecde140a561c64e297225904afebebd62336cejljusten // 306bcecde140a561c64e297225904afebebd62336cejljusten Status = LegacyBiosGetFlatDescs (Private); 307bcecde140a561c64e297225904afebebd62336cejljusten ASSERT_EFI_ERROR (Status); 308bcecde140a561c64e297225904afebebd62336cejljusten 309bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.Reserved1 = 1; 310bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.Reserved2 = 0; 311bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.Reserved3 = 0; 312bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.Reserved4 = 0; 313bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.IOPL = 3; 314bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.NT = 0; 315bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.IF = 1; 316bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.TF = 0; 317bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.CF = 0; 318bcecde140a561c64e297225904afebebd62336cejljusten // 319bcecde140a561c64e297225904afebebd62336cejljusten // Clear the error flag; thunk code may set it. 320bcecde140a561c64e297225904afebebd62336cejljusten // 321bcecde140a561c64e297225904afebebd62336cejljusten Stack16 = (UINT16 *) (IntThunk->Stack + LOW_STACK_SIZE); 322bcecde140a561c64e297225904afebebd62336cejljusten 323bcecde140a561c64e297225904afebebd62336cejljusten // 324bcecde140a561c64e297225904afebebd62336cejljusten // Copy regs to low memory stack 325bcecde140a561c64e297225904afebebd62336cejljusten // 326bcecde140a561c64e297225904afebebd62336cejljusten Stack16 -= sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16); 327bcecde140a561c64e297225904afebebd62336cejljusten CopyMem (Stack16, Regs, sizeof (EFI_IA32_REGISTER_SET)); 328bcecde140a561c64e297225904afebebd62336cejljusten 329bcecde140a561c64e297225904afebebd62336cejljusten // 330bcecde140a561c64e297225904afebebd62336cejljusten // Provide low stack esp 331bcecde140a561c64e297225904afebebd62336cejljusten // 332bcecde140a561c64e297225904afebebd62336cejljusten TempData = ((UINTN) Stack16) - ((UINTN) IntThunk); 333bcecde140a561c64e297225904afebebd62336cejljusten IntThunk->LowStack = *((UINT32 *) &TempData); 334bcecde140a561c64e297225904afebebd62336cejljusten 335bcecde140a561c64e297225904afebebd62336cejljusten // 336bcecde140a561c64e297225904afebebd62336cejljusten // Stack for reverse thunk flat mode. 337bcecde140a561c64e297225904afebebd62336cejljusten // It must point to top of stack (end of stack space). 338bcecde140a561c64e297225904afebebd62336cejljusten // 339bcecde140a561c64e297225904afebebd62336cejljusten TempData = ((UINTN) IntThunk->RevThunkStack) + LOW_STACK_SIZE; 340bcecde140a561c64e297225904afebebd62336cejljusten IntThunk->RevFlatStack = *((UINT32 *) &TempData); 341bcecde140a561c64e297225904afebebd62336cejljusten 342bcecde140a561c64e297225904afebebd62336cejljusten // 343bcecde140a561c64e297225904afebebd62336cejljusten // The call to Legacy16 is a critical section to EFI 344bcecde140a561c64e297225904afebebd62336cejljusten // 345bcecde140a561c64e297225904afebebd62336cejljusten OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); 346bcecde140a561c64e297225904afebebd62336cejljusten 347bcecde140a561c64e297225904afebebd62336cejljusten // 348bcecde140a561c64e297225904afebebd62336cejljusten // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. 349bcecde140a561c64e297225904afebebd62336cejljusten // 350bcecde140a561c64e297225904afebebd62336cejljusten Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL); 351bcecde140a561c64e297225904afebebd62336cejljusten ASSERT_EFI_ERROR (Status); 352bcecde140a561c64e297225904afebebd62336cejljusten 353bcecde140a561c64e297225904afebebd62336cejljusten // 354bcecde140a561c64e297225904afebebd62336cejljusten // Call the real mode thunk code 355bcecde140a561c64e297225904afebebd62336cejljusten // 356bcecde140a561c64e297225904afebebd62336cejljusten TempData = BiosInt * 4; 357bcecde140a561c64e297225904afebebd62336cejljusten Address = (UINTN *) TempData; 358bcecde140a561c64e297225904afebebd62336cejljusten IaOffset = 0xFFFF & (*Address); 359bcecde140a561c64e297225904afebebd62336cejljusten IaSegment = 0xFFFF & ((*Address) >> 16); 360bcecde140a561c64e297225904afebebd62336cejljusten 361bcecde140a561c64e297225904afebebd62336cejljusten Status = BiosIntCall ( 362bcecde140a561c64e297225904afebebd62336cejljusten BiosInt, 363bcecde140a561c64e297225904afebebd62336cejljusten (UINT16) IaSegment, 364bcecde140a561c64e297225904afebebd62336cejljusten (UINT16) IaOffset, 365bcecde140a561c64e297225904afebebd62336cejljusten (EFI_IA32_REGISTER_SET *) Stack16, 366bcecde140a561c64e297225904afebebd62336cejljusten IntThunk, 367bcecde140a561c64e297225904afebebd62336cejljusten IntThunk->LowStack 368bcecde140a561c64e297225904afebebd62336cejljusten ); 369bcecde140a561c64e297225904afebebd62336cejljusten 370bcecde140a561c64e297225904afebebd62336cejljusten // 371bcecde140a561c64e297225904afebebd62336cejljusten // Check for errors with the thunk 372bcecde140a561c64e297225904afebebd62336cejljusten // 373bcecde140a561c64e297225904afebebd62336cejljusten switch (Status) { 374bcecde140a561c64e297225904afebebd62336cejljusten case THUNK_OK: 375bcecde140a561c64e297225904afebebd62336cejljusten break; 376bcecde140a561c64e297225904afebebd62336cejljusten 377bcecde140a561c64e297225904afebebd62336cejljusten case THUNK_ERR_A20_UNSUP: 378bcecde140a561c64e297225904afebebd62336cejljusten case THUNK_ERR_A20_FAILED: 379bcecde140a561c64e297225904afebebd62336cejljusten default: 380bcecde140a561c64e297225904afebebd62336cejljusten // 381bcecde140a561c64e297225904afebebd62336cejljusten // For all errors, set EFLAGS.CF (used by legacy BIOS to indicate error). 382bcecde140a561c64e297225904afebebd62336cejljusten // 383bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.CF = 1; 384bcecde140a561c64e297225904afebebd62336cejljusten break; 385bcecde140a561c64e297225904afebebd62336cejljusten } 386bcecde140a561c64e297225904afebebd62336cejljusten 387bcecde140a561c64e297225904afebebd62336cejljusten Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL); 388bcecde140a561c64e297225904afebebd62336cejljusten ASSERT_EFI_ERROR (Status); 389bcecde140a561c64e297225904afebebd62336cejljusten 390bcecde140a561c64e297225904afebebd62336cejljusten // 391bcecde140a561c64e297225904afebebd62336cejljusten // End critical section 392bcecde140a561c64e297225904afebebd62336cejljusten // 393bcecde140a561c64e297225904afebebd62336cejljusten gBS->RestoreTPL (OriginalTpl); 394bcecde140a561c64e297225904afebebd62336cejljusten 395bcecde140a561c64e297225904afebebd62336cejljusten // 396bcecde140a561c64e297225904afebebd62336cejljusten // Return the resulting registers 397bcecde140a561c64e297225904afebebd62336cejljusten // 398bcecde140a561c64e297225904afebebd62336cejljusten CopyMem (Regs, Stack16, sizeof (EFI_IA32_REGISTER_SET)); 399bcecde140a561c64e297225904afebebd62336cejljusten 400bcecde140a561c64e297225904afebebd62336cejljusten return (BOOLEAN) (Regs->X.Flags.CF != 0); 401bcecde140a561c64e297225904afebebd62336cejljusten} 402bcecde140a561c64e297225904afebebd62336cejljusten 403bcecde140a561c64e297225904afebebd62336cejljusten 404bcecde140a561c64e297225904afebebd62336cejljusten/** 405bcecde140a561c64e297225904afebebd62336cejljusten Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the 406bcecde140a561c64e297225904afebebd62336cejljusten 16-bit register context on entry and exit. Arguments can be passed on 407bcecde140a561c64e297225904afebebd62336cejljusten the Stack argument 408bcecde140a561c64e297225904afebebd62336cejljusten 409bcecde140a561c64e297225904afebebd62336cejljusten @param This Protocol instance pointer. 410bcecde140a561c64e297225904afebebd62336cejljusten @param Segment Segemnt of 16-bit mode call 411bcecde140a561c64e297225904afebebd62336cejljusten @param Offset Offset of 16-bit mdoe call 412bcecde140a561c64e297225904afebebd62336cejljusten @param Regs Register contexted passed into (and returned) from 413bcecde140a561c64e297225904afebebd62336cejljusten thunk to 16-bit mode 414bcecde140a561c64e297225904afebebd62336cejljusten @param Stack Caller allocated stack used to pass arguments 415bcecde140a561c64e297225904afebebd62336cejljusten @param StackSize Size of Stack in bytes 416bcecde140a561c64e297225904afebebd62336cejljusten 417bcecde140a561c64e297225904afebebd62336cejljusten @retval FALSE Thunk completed, and there were no BIOS errors in the 418bcecde140a561c64e297225904afebebd62336cejljusten target code. See Regs for status. 419bcecde140a561c64e297225904afebebd62336cejljusten @retval TRUE There was a BIOS erro in the target code. 420bcecde140a561c64e297225904afebebd62336cejljusten 421bcecde140a561c64e297225904afebebd62336cejljusten**/ 422bcecde140a561c64e297225904afebebd62336cejljustenBOOLEAN 423bcecde140a561c64e297225904afebebd62336cejljustenEFIAPI 424bcecde140a561c64e297225904afebebd62336cejljustenLegacyBiosFarCall86 ( 425bcecde140a561c64e297225904afebebd62336cejljusten IN EFI_LEGACY_BIOS_PROTOCOL *This, 426bcecde140a561c64e297225904afebebd62336cejljusten IN UINT16 Segment, 427bcecde140a561c64e297225904afebebd62336cejljusten IN UINT16 Offset, 428bcecde140a561c64e297225904afebebd62336cejljusten IN EFI_IA32_REGISTER_SET *Regs, 429bcecde140a561c64e297225904afebebd62336cejljusten IN VOID *Stack, 430bcecde140a561c64e297225904afebebd62336cejljusten IN UINTN StackSize 431bcecde140a561c64e297225904afebebd62336cejljusten ) 432bcecde140a561c64e297225904afebebd62336cejljusten{ 433bcecde140a561c64e297225904afebebd62336cejljusten EFI_STATUS Status; 434bcecde140a561c64e297225904afebebd62336cejljusten LEGACY_BIOS_INSTANCE *Private; 435bcecde140a561c64e297225904afebebd62336cejljusten LOW_MEMORY_THUNK *IntThunk; 436bcecde140a561c64e297225904afebebd62336cejljusten UINT16 *Stack16; 437bcecde140a561c64e297225904afebebd62336cejljusten EFI_TPL OriginalTpl; 438bcecde140a561c64e297225904afebebd62336cejljusten UINTN IaSegment; 439bcecde140a561c64e297225904afebebd62336cejljusten UINTN IaOffset; 440bcecde140a561c64e297225904afebebd62336cejljusten UINTN TempData; 441bcecde140a561c64e297225904afebebd62336cejljusten 442bcecde140a561c64e297225904afebebd62336cejljusten Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This); 443bcecde140a561c64e297225904afebebd62336cejljusten IntThunk = Private->IntThunk; 444bcecde140a561c64e297225904afebebd62336cejljusten IaSegment = Segment; 445bcecde140a561c64e297225904afebebd62336cejljusten IaOffset = Offset; 446bcecde140a561c64e297225904afebebd62336cejljusten 447bcecde140a561c64e297225904afebebd62336cejljusten // 448bcecde140a561c64e297225904afebebd62336cejljusten // Get the current flat GDT and IDT and store them in Private->IntThunk. 449bcecde140a561c64e297225904afebebd62336cejljusten // 450bcecde140a561c64e297225904afebebd62336cejljusten Status = LegacyBiosGetFlatDescs (Private); 451bcecde140a561c64e297225904afebebd62336cejljusten ASSERT_EFI_ERROR (Status); 452bcecde140a561c64e297225904afebebd62336cejljusten 453bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.Reserved1 = 1; 454bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.Reserved2 = 0; 455bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.Reserved3 = 0; 456bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.Reserved4 = 0; 457bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.IOPL = 3; 458bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.NT = 0; 459bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.IF = 1; 460bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.TF = 0; 461bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.CF = 0; 462bcecde140a561c64e297225904afebebd62336cejljusten // 463bcecde140a561c64e297225904afebebd62336cejljusten // Clear the error flag; thunk code may set it. 464bcecde140a561c64e297225904afebebd62336cejljusten // 465bcecde140a561c64e297225904afebebd62336cejljusten Stack16 = (UINT16 *) (IntThunk->Stack + LOW_STACK_SIZE); 466bcecde140a561c64e297225904afebebd62336cejljusten if (Stack != NULL && StackSize != 0) { 467bcecde140a561c64e297225904afebebd62336cejljusten // 468bcecde140a561c64e297225904afebebd62336cejljusten // Copy Stack to low memory stack 469bcecde140a561c64e297225904afebebd62336cejljusten // 470bcecde140a561c64e297225904afebebd62336cejljusten Stack16 -= StackSize / sizeof (UINT16); 471bcecde140a561c64e297225904afebebd62336cejljusten CopyMem (Stack16, Stack, StackSize); 472bcecde140a561c64e297225904afebebd62336cejljusten } 473bcecde140a561c64e297225904afebebd62336cejljusten // 474bcecde140a561c64e297225904afebebd62336cejljusten // Copy regs to low memory stack 475bcecde140a561c64e297225904afebebd62336cejljusten // 476bcecde140a561c64e297225904afebebd62336cejljusten Stack16 -= sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16); 477bcecde140a561c64e297225904afebebd62336cejljusten CopyMem (Stack16, Regs, sizeof (EFI_IA32_REGISTER_SET)); 478bcecde140a561c64e297225904afebebd62336cejljusten 479bcecde140a561c64e297225904afebebd62336cejljusten // 480bcecde140a561c64e297225904afebebd62336cejljusten // Provide low stack esp 481bcecde140a561c64e297225904afebebd62336cejljusten // 482bcecde140a561c64e297225904afebebd62336cejljusten TempData = ((UINTN) Stack16) - ((UINTN) IntThunk); 483bcecde140a561c64e297225904afebebd62336cejljusten IntThunk->LowStack = *((UINT32 *) &TempData); 484bcecde140a561c64e297225904afebebd62336cejljusten 485bcecde140a561c64e297225904afebebd62336cejljusten // 486bcecde140a561c64e297225904afebebd62336cejljusten // The call to Legacy16 is a critical section to EFI 487bcecde140a561c64e297225904afebebd62336cejljusten // 488bcecde140a561c64e297225904afebebd62336cejljusten OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); 489bcecde140a561c64e297225904afebebd62336cejljusten 490bcecde140a561c64e297225904afebebd62336cejljusten // 491bcecde140a561c64e297225904afebebd62336cejljusten // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. 492bcecde140a561c64e297225904afebebd62336cejljusten // 493bcecde140a561c64e297225904afebebd62336cejljusten Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259LegacyMode, NULL, NULL); 494bcecde140a561c64e297225904afebebd62336cejljusten ASSERT_EFI_ERROR (Status); 495bcecde140a561c64e297225904afebebd62336cejljusten 496bcecde140a561c64e297225904afebebd62336cejljusten // 497bcecde140a561c64e297225904afebebd62336cejljusten // Call the real mode thunk code 498bcecde140a561c64e297225904afebebd62336cejljusten // 499bcecde140a561c64e297225904afebebd62336cejljusten Status = BiosIntCall ( 500bcecde140a561c64e297225904afebebd62336cejljusten 0x100, 501bcecde140a561c64e297225904afebebd62336cejljusten (UINT16) IaSegment, 502bcecde140a561c64e297225904afebebd62336cejljusten (UINT16) IaOffset, 503bcecde140a561c64e297225904afebebd62336cejljusten (EFI_IA32_REGISTER_SET *) Stack16, 504bcecde140a561c64e297225904afebebd62336cejljusten IntThunk, 505bcecde140a561c64e297225904afebebd62336cejljusten IntThunk->LowStack 506bcecde140a561c64e297225904afebebd62336cejljusten ); 507bcecde140a561c64e297225904afebebd62336cejljusten 508bcecde140a561c64e297225904afebebd62336cejljusten // 509bcecde140a561c64e297225904afebebd62336cejljusten // Check for errors with the thunk 510bcecde140a561c64e297225904afebebd62336cejljusten // 511bcecde140a561c64e297225904afebebd62336cejljusten switch (Status) { 512bcecde140a561c64e297225904afebebd62336cejljusten case THUNK_OK: 513bcecde140a561c64e297225904afebebd62336cejljusten break; 514bcecde140a561c64e297225904afebebd62336cejljusten 515bcecde140a561c64e297225904afebebd62336cejljusten case THUNK_ERR_A20_UNSUP: 516bcecde140a561c64e297225904afebebd62336cejljusten case THUNK_ERR_A20_FAILED: 517bcecde140a561c64e297225904afebebd62336cejljusten default: 518bcecde140a561c64e297225904afebebd62336cejljusten // 519bcecde140a561c64e297225904afebebd62336cejljusten // For all errors, set EFLAGS.CF (used by legacy BIOS to indicate error). 520bcecde140a561c64e297225904afebebd62336cejljusten // 521bcecde140a561c64e297225904afebebd62336cejljusten Regs->X.Flags.CF = 1; 522bcecde140a561c64e297225904afebebd62336cejljusten break; 523bcecde140a561c64e297225904afebebd62336cejljusten } 524bcecde140a561c64e297225904afebebd62336cejljusten // 525bcecde140a561c64e297225904afebebd62336cejljusten // Restore protected mode interrupt state 526bcecde140a561c64e297225904afebebd62336cejljusten // 527bcecde140a561c64e297225904afebebd62336cejljusten Status = Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259ProtectedMode, NULL, NULL); 528bcecde140a561c64e297225904afebebd62336cejljusten ASSERT_EFI_ERROR (Status); 529bcecde140a561c64e297225904afebebd62336cejljusten 530bcecde140a561c64e297225904afebebd62336cejljusten // 531bcecde140a561c64e297225904afebebd62336cejljusten // End critical section 532bcecde140a561c64e297225904afebebd62336cejljusten // 533bcecde140a561c64e297225904afebebd62336cejljusten gBS->RestoreTPL (OriginalTpl); 534bcecde140a561c64e297225904afebebd62336cejljusten 535bcecde140a561c64e297225904afebebd62336cejljusten // 536bcecde140a561c64e297225904afebebd62336cejljusten // Return the resulting registers 537bcecde140a561c64e297225904afebebd62336cejljusten // 538bcecde140a561c64e297225904afebebd62336cejljusten CopyMem (Regs, Stack16, sizeof (EFI_IA32_REGISTER_SET)); 539bcecde140a561c64e297225904afebebd62336cejljusten Stack16 += sizeof (EFI_IA32_REGISTER_SET) / sizeof (UINT16); 540bcecde140a561c64e297225904afebebd62336cejljusten 541bcecde140a561c64e297225904afebebd62336cejljusten if (Stack != NULL && StackSize != 0) { 542bcecde140a561c64e297225904afebebd62336cejljusten // 543bcecde140a561c64e297225904afebebd62336cejljusten // Copy low memory stack to Stack 544bcecde140a561c64e297225904afebebd62336cejljusten // 545bcecde140a561c64e297225904afebebd62336cejljusten CopyMem (Stack, Stack16, StackSize); 546bcecde140a561c64e297225904afebebd62336cejljusten Stack16 += StackSize / sizeof (UINT16); 547bcecde140a561c64e297225904afebebd62336cejljusten } 548bcecde140a561c64e297225904afebebd62336cejljusten 549bcecde140a561c64e297225904afebebd62336cejljusten return (BOOLEAN) (Regs->X.Flags.CF != 0); 550bcecde140a561c64e297225904afebebd62336cejljusten} 551