EFIAPI FspFindFspHeader ( IN EFI_PHYSICAL_ADDRESS FlashFvFspBase ) { UINT8 *CheckPointer; CheckPointer = (UINT8 *) (UINTN) FlashFvFspBase; if (((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->Signature != EFI_FVH_SIGNATURE) { return NULL; } if (((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->ExtHeaderOffset != 0) { CheckPointer = CheckPointer + ((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->ExtHeaderOffset; CheckPointer = CheckPointer + ((EFI_FIRMWARE_VOLUME_EXT_HEADER *)CheckPointer)->ExtHeaderSize; CheckPointer = (UINT8 *) ALIGN_POINTER (CheckPointer, 8); } else { CheckPointer = CheckPointer + ((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->HeaderLength; } if (!CompareGuid (&((EFI_FFS_FILE_HEADER *)CheckPointer)->Name, &gFspHeaderFileGuid)) { return NULL; } CheckPointer = CheckPointer + sizeof (EFI_FFS_FILE_HEADER); if (((EFI_RAW_SECTION *)CheckPointer)->Type != EFI_SECTION_RAW) { return NULL; } CheckPointer = CheckPointer + sizeof (EFI_RAW_SECTION); return (FSP_INFO_HEADER *)CheckPointer; }
unsigned char * WINAPI CLEANLOCALSTORAGE_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstg) { ALIGN_POINTER(Buffer, 3); *(DWORD*)Buffer = pstg->flags; switch(pstg->flags) { case CLS_LIBATTR: ITypeLib_ReleaseTLibAttr((ITypeLib*)pstg->pInterface, *(TLIBATTR**)pstg->pStorage); break; case CLS_TYPEATTR: ITypeInfo_ReleaseTypeAttr((ITypeInfo*)pstg->pInterface, *(TYPEATTR**)pstg->pStorage); break; case CLS_FUNCDESC: ITypeInfo_ReleaseFuncDesc((ITypeInfo*)pstg->pInterface, *(FUNCDESC**)pstg->pStorage); break; case CLS_VARDESC: ITypeInfo_ReleaseVarDesc((ITypeInfo*)pstg->pInterface, *(VARDESC**)pstg->pStorage); break; default: ERR("Unknown type %lx\n", pstg->flags); } *(VOID**)pstg->pStorage = NULL; IUnknown_Release(pstg->pInterface); pstg->pInterface = NULL; return Buffer + sizeof(DWORD); }
/** Initialize Global Descriptor Table. **/ VOID InitGlobalDescriptorTable ( VOID ) { GDT_ENTRIES *gdt; IA32_DESCRIPTOR gdtPtr; // // Allocate Runtime Data for the GDT // gdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8); ASSERT (gdt != NULL); gdt = ALIGN_POINTER (gdt, 8); // // Initialize all GDT entries // CopyMem (gdt, &GdtTemplate, sizeof (GdtTemplate)); // // Write GDT register // gdtPtr.Base = (UINT32)(UINTN)(VOID*) gdt; gdtPtr.Limit = (UINT16) (sizeof (GdtTemplate) - 1); AsmWriteGdtr (&gdtPtr); // // Update selector (segment) registers base on new GDT // SetCodeSelector ((UINT16)CPU_CODE_SEL); SetDataSelectors ((UINT16)CPU_DATA_SEL); }
unsigned char * __RPC_USER STGMEDIUM_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, STGMEDIUM *pStgMedium) { DWORD content; DWORD releaseunk; ALIGN_POINTER(pBuffer, 3); TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", pBuffer, pStgMedium); pStgMedium->tymed = *(DWORD *)pBuffer; pBuffer += sizeof(DWORD); if (pStgMedium->tymed != TYMED_NULL) { content = *(DWORD *)pBuffer; pBuffer += sizeof(DWORD); } releaseunk = *(DWORD *)pBuffer; pBuffer += sizeof(DWORD); switch (pStgMedium->tymed) { case TYMED_NULL: TRACE("TYMED_NULL\n"); break; case TYMED_HGLOBAL: TRACE("TYMED_HGLOBAL\n"); pBuffer = HGLOBAL_UserUnmarshal(pFlags, pBuffer, &pStgMedium->u.hGlobal); break; case TYMED_FILE: FIXME("TYMED_FILE\n"); break; case TYMED_ISTREAM: FIXME("TYMED_ISTREAM\n"); break; case TYMED_ISTORAGE: FIXME("TYMED_ISTORAGE\n"); break; case TYMED_GDI: FIXME("TYMED_GDI\n"); break; case TYMED_MFPICT: FIXME("TYMED_MFPICT\n"); break; case TYMED_ENHMF: TRACE("TYMED_ENHMF\n"); pBuffer = HENHMETAFILE_UserUnmarshal(pFlags, pBuffer, &pStgMedium->u.hEnhMetaFile); break; default: RaiseException(DV_E_TYMED, 0, 0, NULL); } pStgMedium->pUnkForRelease = NULL; if (releaseunk) FIXME("unmarshal pUnkForRelease\n"); return pBuffer; }
/** Transfers control to DxeCore. This function performs a CPU architecture specific operations to execute the entry point of DxeCore with the parameters of HobList. It also installs EFI_END_OF_PEI_PPI to signal the end of PEI phase. @param DxeCoreEntryPoint The entry point of DxeCore. @param HobList The start of HobList passed to DxeCore. **/ VOID HandOffToDxeCore ( IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint, IN EFI_PEI_HOB_POINTERS HobList ) { VOID *BaseOfStack; VOID *TopOfStack; EFI_STATUS Status; UINTN PageTables; // // Allocate 128KB for the Stack // BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE)); ASSERT (BaseOfStack != NULL); // // Compute the top of the stack we were allocated. Pre-allocate a UINTN // for safety. // TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT); TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); PageTables = 0; if (FeaturePcdGet (PcdDxeIplBuildPageTables)) { // // Create page table and save PageMapLevel4 to CR3 // PageTables = CreateIdentityMappingPageTables (); } // // End of PEI phase signal // Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi); ASSERT_EFI_ERROR (Status); if (FeaturePcdGet (PcdDxeIplBuildPageTables)) { AsmWriteCr3 (PageTables); } // // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. // UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, STACK_SIZE); // // Transfer the control to the entry point of DxeCore. // SwitchStack ( (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, HobList.Raw, NULL, TopOfStack ); }
EFI_STATUS FvBufFindNextSection ( IN VOID *SectionsStart, IN UINTN TotalSectionsSize, IN OUT UINTN *Key, OUT VOID **Section ) /*++ Routine Description: Iterates through the sections contained within a given array of sections Arguments: SectionsStart - Address of the start of the FFS sections array TotalSectionsSize - Total size of all the sections Key - Should be 0 to get the first section. After that, it should be passed back in without modifying it's contents to retrieve subsequent files. Section - Output section pointer (Section == NULL) -> invalid parameter otherwise -> *Section will be update to the location of the file Returns: EFI_SUCCESS EFI_NOT_FOUND EFI_VOLUME_CORRUPTED --*/ { EFI_COMMON_SECTION_HEADER *sectionHdr; UINTN sectionSize; *Key = (UINTN)ALIGN_POINTER (*Key, 4); // Sections are DWORD aligned if ((*Key + sizeof (*sectionHdr)) > TotalSectionsSize) { return EFI_NOT_FOUND; } sectionHdr = (EFI_COMMON_SECTION_HEADER*)((UINT8*)SectionsStart + *Key); sectionSize = FvBufExpand3ByteSize (sectionHdr->Size); if (sectionSize < sizeof (EFI_COMMON_SECTION_HEADER)) { return EFI_NOT_FOUND; } if ((*Key + sectionSize) > TotalSectionsSize) { return EFI_NOT_FOUND; } *Section = (UINT8*)sectionHdr; *Key = *Key + sectionSize; return EFI_SUCCESS; }
/** Transfers control to DxeCore. This function performs a CPU architecture specific operations to execute the entry point of DxeCore with the parameters of HobList. It also installs EFI_END_OF_PEI_PPI to signal the end of PEI phase. @param DxeCoreEntryPoint The entry point of DxeCore. @param HobList The start of HobList passed to DxeCore. **/ VOID HandOffToDxeCore ( IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint, IN EFI_PEI_HOB_POINTERS HobList ) { VOID *BaseOfStack; VOID *TopOfStack; EFI_STATUS Status; // // // Allocate 128KB for the Stack // BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE)); ASSERT (BaseOfStack != NULL); // // Compute the top of the stack we were allocated. Pre-allocate a UINTN // for safety. // TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT); TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); // // End of PEI phase signal // Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi); ASSERT_EFI_ERROR (Status); // // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. // UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, STACK_SIZE); DEBUG ((EFI_D_INFO, "DXE Core new stack at %x, stack pointer at %x\n", BaseOfStack, TopOfStack)); // // Transfer the control to the entry point of DxeCore. // SwitchStack ( (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, HobList.Raw, NULL, TopOfStack ); }
/** Transfers control to DxeCore. This function performs a CPU architecture specific operations to execute the entry point of DxeCore with the parameters of HobList. It also installs EFI_END_OF_PEI_PPI to signal the end of PEI phase. @param DxeCoreEntryPoint The entry point of DxeCore. @param HobList The start of HobList passed to DxeCore. **/ VOID HandOffToDxeCore ( IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint, IN EFI_PEI_HOB_POINTERS HobList ) { VOID *BaseOfStack; VOID *TopOfStack; EFI_STATUS Status; // // Allocate 128KB for the Stack // BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE)); ASSERT (BaseOfStack != NULL); if (PcdGetBool (PcdSetNxForStack)) { Status = ArmSetMemoryRegionNoExec ((UINTN)BaseOfStack, STACK_SIZE); ASSERT_EFI_ERROR (Status); } // // Compute the top of the stack we were allocated. Pre-allocate a UINTN // for safety. // TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT); TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); // // End of PEI phase singal // Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi); ASSERT_EFI_ERROR (Status); // // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. // UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, STACK_SIZE); SwitchStack ( (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, HobList.Raw, NULL, TopOfStack ); }
/** Initialize Global Descriptor Table. **/ VOID InitLinuxDescriptorTables ( VOID ) { // // Allocate Runtime Data for the GDT // mGdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8); ASSERT (mGdt != NULL); mGdt = ALIGN_POINTER (mGdt, 8); // // Initialize all GDT entries // CopyMem (mGdt, &GdtTemplate, sizeof (GdtTemplate)); }
unsigned char * __RPC_USER HGLOBAL_UserMarshal(unsigned long *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal) { TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", pBuffer, *phGlobal); ALIGN_POINTER(pBuffer, 3); if (LOWORD(*pFlags == MSHCTX_INPROC)) { if (sizeof(*phGlobal) == 8) *(ULONG *)pBuffer = WDT_INPROC64_CALL; else *(ULONG *)pBuffer = WDT_INPROC_CALL; pBuffer += sizeof(ULONG); *(HGLOBAL *)pBuffer = *phGlobal; pBuffer += sizeof(HGLOBAL); } else { *(ULONG *)pBuffer = WDT_REMOTE_CALL; pBuffer += sizeof(ULONG); *(ULONG *)pBuffer = (ULONG)*phGlobal; pBuffer += sizeof(ULONG); if (*phGlobal) { const unsigned char *memory; SIZE_T size = GlobalSize(*phGlobal); *(ULONG *)pBuffer = (ULONG)size; pBuffer += sizeof(ULONG); *(ULONG *)pBuffer = (ULONG)*phGlobal; pBuffer += sizeof(ULONG); *(ULONG *)pBuffer = (ULONG)size; pBuffer += sizeof(ULONG); memory = GlobalLock(*phGlobal); memcpy(pBuffer, memory, size); pBuffer += size; GlobalUnlock(*phGlobal); } } return pBuffer; }
unsigned char * WINAPI BSTR_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr) { bstr_wire_t *header; DWORD len = SysStringByteLen(*pstr); TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr); if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr)); ALIGN_POINTER(Buffer, 3); header = (bstr_wire_t*)Buffer; header->len = header->len2 = (len + 1) / 2; if (*pstr) { header->byte_len = len; memcpy(header + 1, *pstr, header->len * 2); } else header->byte_len = 0xffffffff; /* special case for a null bstr */ return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len; }
unsigned char * WINAPI BSTR_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr) { bstr_wire_t *header; TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr); ALIGN_POINTER(Buffer, 3); header = (bstr_wire_t*)Buffer; if(header->len != header->len2) FIXME("len %08lx != len2 %08lx\n", header->len, header->len2); if(*pstr) { SysFreeString(*pstr); *pstr = NULL; } if(header->byte_len != 0xffffffff) *pstr = SysAllocStringByteLen((char*)(header + 1), header->byte_len); if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr)); return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len; }
unsigned char * WINAPI VARIANT_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar) { variant_wire_t *header; unsigned long type_size; int align; unsigned char *Pos; TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar); TRACE("vt=%04x\n", V_VT(pvar)); ALIGN_POINTER(Buffer, 7); header = (variant_wire_t *)Buffer; header->clSize = 0; /* fixed up at the end */ header->rpcReserverd = 0; header->vt = pvar->n1.n2.vt; header->wReserved1 = pvar->n1.n2.wReserved1; header->wReserved2 = pvar->n1.n2.wReserved2; header->wReserved3 = pvar->n1.n2.wReserved3; header->switch_is = pvar->n1.n2.vt; if(header->switch_is & VT_ARRAY) header->switch_is &= ~VT_TYPEMASK; Pos = (unsigned char*)(header + 1); type_size = get_type_size(pFlags, pvar); align = get_type_alignment(pFlags, pvar); ALIGN_POINTER(Pos, align); if(header->vt & VT_BYREF) { *(DWORD *)Pos = max(type_size, 4); Pos += 4; if((header->vt & VT_TYPEMASK) != VT_VARIANT) { memcpy(Pos, pvar->n1.n2.n3.byref, type_size); Pos += type_size; } else { *(DWORD*)Pos = 'U' | 's' << 8 | 'e' << 16 | 'r' << 24; Pos += 4; } } else { if((header->vt & VT_TYPEMASK) == VT_DECIMAL) memcpy(Pos, pvar, type_size); else memcpy(Pos, &pvar->n1.n2.n3, type_size); Pos += type_size; } if(header->vt & VT_ARRAY) { if(header->vt & VT_BYREF) Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, V_ARRAYREF(pvar)); else Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, &V_ARRAY(pvar)); } else { switch (header->vt) { case VT_BSTR: Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar)); break; case VT_BSTR | VT_BYREF: Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar)); break; case VT_VARIANT | VT_BYREF: Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar)); break; case VT_DISPATCH | VT_BYREF: FIXME("handle DISPATCH by ref\n"); break; case VT_UNKNOWN: /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, pvar); break; case VT_DISPATCH: /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */ Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, pvar); break; case VT_RECORD: FIXME("handle BRECORD by val\n"); break; case VT_RECORD | VT_BYREF: FIXME("handle BRECORD by ref\n"); break; } } header->clSize = ((Pos - Buffer) + 7) >> 3; TRACE("marshalled size=%ld\n", header->clSize); return Pos; }
unsigned char * WINAPI CLEANLOCALSTORAGE_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstr) { ALIGN_POINTER(Buffer, 3); pstr->flags = *(DWORD*)Buffer; return Buffer + sizeof(DWORD); }
/*++ Routine Description: This is the service to load the SEC Core from the Firmware Volume Arguments: LargestRegion - Memory to use for SEC. LargestRegionSize - Size of Memory to use for PEI BootFirmwareVolumeBase - Start of the Boot FV PeiCorePe32File - SEC PE32 Returns: Success means control is transfered and thus we should never return **/ VOID SecLoadFromCore ( IN UINTN LargestRegion, IN UINTN LargestRegionSize, IN UINTN BootFirmwareVolumeBase, IN VOID *PeiCorePe32File ) { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS TopOfMemory; VOID *TopOfStack; EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint; EFI_SEC_PEI_HAND_OFF *SecCoreData; UINTN PeiStackSize; // // Compute Top Of Memory for Stack and PEI Core Allocations // TopOfMemory = LargestRegion + LargestRegionSize; PeiStackSize = (UINTN)RShiftU64((UINT64)STACK_SIZE,1); // // |-----------| <---- TemporaryRamBase + TemporaryRamSize // | Heap | // | | // |-----------| <---- StackBase / PeiTemporaryMemoryBase // | | // | Stack | // |-----------| <---- TemporaryRamBase // TopOfStack = (VOID *)(LargestRegion + PeiStackSize); TopOfMemory = LargestRegion + PeiStackSize; // // Reservet space for storing PeiCore's parament in stack. // TopOfStack = (VOID *)((UINTN)TopOfStack - sizeof (EFI_SEC_PEI_HAND_OFF) - CPU_STACK_ALIGNMENT); TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); // // Bind this information into the SEC hand-off state // SecCoreData = (EFI_SEC_PEI_HAND_OFF*)(UINTN) TopOfStack; SecCoreData->DataSize = sizeof(EFI_SEC_PEI_HAND_OFF); SecCoreData->BootFirmwareVolumeBase = (VOID*)BootFirmwareVolumeBase; SecCoreData->BootFirmwareVolumeSize = PcdGet32 (PcdEmuFirmwareFdSize); SecCoreData->TemporaryRamBase = (VOID*)(UINTN)LargestRegion; SecCoreData->TemporaryRamSize = STACK_SIZE; SecCoreData->StackBase = SecCoreData->TemporaryRamBase; SecCoreData->StackSize = PeiStackSize; SecCoreData->PeiTemporaryRamBase = (VOID*) ((UINTN) SecCoreData->TemporaryRamBase + PeiStackSize); SecCoreData->PeiTemporaryRamSize = STACK_SIZE - PeiStackSize; // // Find the SEC Core Entry Point // Status = SecPeCoffGetEntryPoint (PeiCorePe32File, (VOID **)&PeiCoreEntryPoint); if (EFI_ERROR (Status)) { return ; } // // Transfer control to the SEC Core // PeiSwitchStacks ( (SWITCH_STACK_ENTRY_POINT) (UINTN) PeiCoreEntryPoint, SecCoreData, (VOID *)gPpiList, TopOfStack ); // // If we get here, then the SEC Core returned. This is an error // return ; }
free(ctx->log_extremes_pstats_scratch); ctx->log_extremes_pstats_scratch_size=tmp_size; ctx->log_extremes_pstats_scratch=do_alloc(1, tmp_size); p1=(float *)ctx->log_extremes_pstats_scratch; PRAGMA_IVDEP for(i=0;i<(ctx->log_extremes_pstats_scratch_size/sizeof(*p1));i++)p1[i]=NAN; fprintf(stderr, "Expanded log_extremes_pstats_scratch to %f MB nchunks=%d veto_free=%d count=%d nei=%d\n", ctx->log_extremes_pstats_scratch_size*1e-6, args_info.nchunks_arg, veto_free, count, nei); } p1=(float *)ctx->log_extremes_pstats_scratch; tmp=p1; p1=ALIGN_POINTER(p1+args_info.nchunks_arg*veto_free*fshift_count*tmp_stride); tmp2a=p1; p1=ALIGN_POINTER(p1+tmp_stride*fshift_count); tmp2b=p1; p1=ALIGN_POINTER(p1+tmp_stride*fshift_count); stats=(POWER_SUM_STATS *)p1; p1=ALIGN_POINTER(p1+((nei*count*sizeof(*stats)+3)>>2)); tmp_min_weight=p1; p1=ALIGN_POINTER(p1+args_info.nchunks_arg*veto_free*fshift_count); tmp_max_weight=p1; p1=ALIGN_POINTER(p1+args_info.nchunks_arg*veto_free*fshift_count); total_weight=p1; p1=ALIGN_POINTER(p1+fshift_count); /* Check that size was computed accurately */ if(((char *)p1)-ctx->log_extremes_pstats_scratch>ctx->log_extremes_pstats_scratch_size) { fprintf(stderr, "*** ERROR: log_extremes_pstats_scratch_size=%ld but need %ld memory\n", ctx->log_extremes_pstats_scratch_size, ((char *)p1)-ctx->log_extremes_pstats_scratch); exit(-1); } for(i=0;i<nei;i++) {
/** Performs an Itanium-based specific relocation fixup. @param Reloc The pointer to the relocation record. @param Fixup The pointer to the address to fix up. @param FixupData The pointer to a buffer to log the fixups. @param Adjust The offset to adjust the fixup. @retval RETURN_SUCCESS Succeed to fix the relocation entry. @retval RETURN_UNSUPPOTED Unrecoganized relocation entry. **/ RETURN_STATUS PeCoffLoaderRelocateImageEx ( IN UINT16 *Reloc, IN OUT CHAR8 *Fixup, IN OUT CHAR8 **FixupData, IN UINT64 Adjust ) { UINT64 *Fixup64; UINT64 FixupVal; switch ((*Reloc) >> 12) { case EFI_IMAGE_REL_BASED_IA64_IMM64: // // Align it to bundle address before fixing up the // 64-bit immediate value of the movl instruction. // Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15)); FixupVal = (UINT64)0; // // Extract the lower 32 bits of IMM64 from bundle // EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X, IMM64_IMM7B_SIZE_X, IMM64_IMM7B_INST_WORD_POS_X, IMM64_IMM7B_VAL_POS_X ); EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X, IMM64_IMM9D_SIZE_X, IMM64_IMM9D_INST_WORD_POS_X, IMM64_IMM9D_VAL_POS_X ); EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X, IMM64_IMM5C_SIZE_X, IMM64_IMM5C_INST_WORD_POS_X, IMM64_IMM5C_VAL_POS_X ); EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IC_INST_WORD_X, IMM64_IC_SIZE_X, IMM64_IC_INST_WORD_POS_X, IMM64_IC_VAL_POS_X ); EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IMM41A_INST_WORD_X, IMM64_IMM41A_SIZE_X, IMM64_IMM41A_INST_WORD_POS_X, IMM64_IMM41A_VAL_POS_X ); // // Update 64-bit address // FixupVal += Adjust; // // Insert IMM64 into bundle // INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X), IMM64_IMM7B_SIZE_X, IMM64_IMM7B_INST_WORD_POS_X, IMM64_IMM7B_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X), IMM64_IMM9D_SIZE_X, IMM64_IMM9D_INST_WORD_POS_X, IMM64_IMM9D_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X), IMM64_IMM5C_SIZE_X, IMM64_IMM5C_INST_WORD_POS_X, IMM64_IMM5C_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X), IMM64_IC_SIZE_X, IMM64_IC_INST_WORD_POS_X, IMM64_IC_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM41A_INST_WORD_X), IMM64_IMM41A_SIZE_X, IMM64_IMM41A_INST_WORD_POS_X, IMM64_IMM41A_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM41B_INST_WORD_X), IMM64_IMM41B_SIZE_X, IMM64_IMM41B_INST_WORD_POS_X, IMM64_IMM41B_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM41C_INST_WORD_X), IMM64_IMM41C_SIZE_X, IMM64_IMM41C_INST_WORD_POS_X, IMM64_IMM41C_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X), IMM64_SIGN_SIZE_X, IMM64_SIGN_INST_WORD_POS_X, IMM64_SIGN_VAL_POS_X ); Fixup64 = (UINT64 *) Fixup; if (*FixupData != NULL) { *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); *(UINT64 *)(*FixupData) = *Fixup64; *FixupData = *FixupData + sizeof(UINT64); } break; default: return RETURN_UNSUPPORTED; } return RETURN_SUCCESS; }
/** Transfers control to DxeCore. This function performs a CPU architecture specific operations to execute the entry point of DxeCore with the parameters of HobList. It also installs EFI_END_OF_PEI_PPI to signal the end of PEI phase. @param DxeCoreEntryPoint The entry point of DxeCore. @param HobList The start of HobList passed to DxeCore. **/ VOID HandOffToDxeCore ( IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint, IN EFI_PEI_HOB_POINTERS HobList ) { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS BaseOfStack; EFI_PHYSICAL_ADDRESS TopOfStack; UINTN PageTables; X64_IDT_GATE_DESCRIPTOR *IdtTable; UINTN SizeOfTemplate; VOID *TemplateBase; EFI_PHYSICAL_ADDRESS VectorAddress; UINT32 Index; X64_IDT_TABLE *IdtTableForX64; EFI_VECTOR_HANDOFF_INFO *VectorInfo; EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi; BOOLEAN BuildPageTablesIa32Pae; if (IsNullDetectionEnabled ()) { ClearFirst4KPage (HobList.Raw); } Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack); ASSERT_EFI_ERROR (Status); if (FeaturePcdGet(PcdDxeIplSwitchToLongMode)) { // // Compute the top of the stack we were allocated, which is used to load X64 dxe core. // Pre-allocate a 32 bytes which confroms to x64 calling convention. // // The first four parameters to a function are passed in rcx, rdx, r8 and r9. // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the // register parameters is reserved on the stack, in case the called function // wants to spill them; this is important if the function is variadic. // TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32; // // x64 Calling Conventions requires that the stack must be aligned to 16 bytes // TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16); // // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA // memory, it may be corrupted when copying FV to high-end memory // AsmWriteGdtr (&gGdt); // // Create page table and save PageMapLevel4 to CR3 // PageTables = CreateIdentityMappingPageTables (BaseOfStack, STACK_SIZE); // // End of PEI phase signal // PERF_EVENT_SIGNAL_BEGIN (gEndOfPeiSignalPpi.Guid); Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi); PERF_EVENT_SIGNAL_END (gEndOfPeiSignalPpi.Guid); ASSERT_EFI_ERROR (Status); // // Paging might be already enabled. To avoid conflict configuration, // disable paging first anyway. // AsmWriteCr0 (AsmReadCr0 () & (~BIT31)); AsmWriteCr3 (PageTables); // // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. // UpdateStackHob (BaseOfStack, STACK_SIZE); SizeOfTemplate = AsmGetVectorTemplatInfo (&TemplateBase); Status = PeiServicesAllocatePages ( EfiBootServicesData, EFI_SIZE_TO_PAGES(sizeof (X64_IDT_TABLE) + SizeOfTemplate * IDT_ENTRY_COUNT), &VectorAddress ); ASSERT_EFI_ERROR (Status); // // Store EFI_PEI_SERVICES** in the 4 bytes immediately preceding IDT to avoid that // it may not be gotten correctly after IDT register is re-written. // IdtTableForX64 = (X64_IDT_TABLE *) (UINTN) VectorAddress; IdtTableForX64->PeiService = GetPeiServicesTablePointer (); VectorAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (IdtTableForX64 + 1); IdtTable = IdtTableForX64->IdtTable; for (Index = 0; Index < IDT_ENTRY_COUNT; Index++) { IdtTable[Index].Ia32IdtEntry.Bits.GateType = 0x8e; IdtTable[Index].Ia32IdtEntry.Bits.Reserved_0 = 0; IdtTable[Index].Ia32IdtEntry.Bits.Selector = SYS_CODE64_SEL; IdtTable[Index].Ia32IdtEntry.Bits.OffsetLow = (UINT16) VectorAddress; IdtTable[Index].Ia32IdtEntry.Bits.OffsetHigh = (UINT16) (RShiftU64 (VectorAddress, 16)); IdtTable[Index].Offset32To63 = (UINT32) (RShiftU64 (VectorAddress, 32)); IdtTable[Index].Reserved = 0; CopyMem ((VOID *) (UINTN) VectorAddress, TemplateBase, SizeOfTemplate); AsmVectorFixup ((VOID *) (UINTN) VectorAddress, (UINT8) Index); VectorAddress += SizeOfTemplate; } gLidtDescriptor.Base = (UINTN) IdtTable; // // Disable interrupt of Debug timer, since new IDT table cannot handle it. // SaveAndSetDebugTimerInterrupt (FALSE); AsmWriteIdtr (&gLidtDescriptor); DEBUG (( DEBUG_INFO, "%a() Stack Base: 0x%lx, Stack Size: 0x%x\n", __FUNCTION__, BaseOfStack, STACK_SIZE )); // // Go to Long Mode and transfer control to DxeCore. // Interrupts will not get turned on until the CPU AP is loaded. // Call x64 drivers passing in single argument, a pointer to the HOBs. // AsmEnablePaging64 ( SYS_CODE64_SEL, DxeCoreEntryPoint, (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw), 0, TopOfStack ); } else { // // Get Vector Hand-off Info PPI and build Guided HOB // Status = PeiServicesLocatePpi ( &gEfiVectorHandoffInfoPpiGuid, 0, NULL, (VOID **)&VectorHandoffInfoPpi ); if (Status == EFI_SUCCESS) { DEBUG ((EFI_D_INFO, "Vector Hand-off Info PPI is gotten, GUIDed HOB is created!\n")); VectorInfo = VectorHandoffInfoPpi->Info; Index = 1; while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) { VectorInfo ++; Index ++; } BuildGuidDataHob ( &gEfiVectorHandoffInfoPpiGuid, VectorHandoffInfoPpi->Info, sizeof (EFI_VECTOR_HANDOFF_INFO) * Index ); } // // Compute the top of the stack we were allocated. Pre-allocate a UINTN // for safety. // TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT; TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); PageTables = 0; BuildPageTablesIa32Pae = ToBuildPageTable (); if (BuildPageTablesIa32Pae) { PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE); if (IsEnableNonExecNeeded ()) { EnableExecuteDisableBit(); } } // // End of PEI phase signal // PERF_EVENT_SIGNAL_BEGIN (gEndOfPeiSignalPpi.Guid); Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi); PERF_EVENT_SIGNAL_END (gEndOfPeiSignalPpi.Guid); ASSERT_EFI_ERROR (Status); if (BuildPageTablesIa32Pae) { // // Paging might be already enabled. To avoid conflict configuration, // disable paging first anyway. // AsmWriteCr0 (AsmReadCr0 () & (~BIT31)); AsmWriteCr3 (PageTables); // // Set Physical Address Extension (bit 5 of CR4). // AsmWriteCr4 (AsmReadCr4 () | BIT5); } // // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. // UpdateStackHob (BaseOfStack, STACK_SIZE); DEBUG (( DEBUG_INFO, "%a() Stack Base: 0x%lx, Stack Size: 0x%x\n", __FUNCTION__, BaseOfStack, STACK_SIZE )); // // Transfer the control to the entry point of DxeCore. // if (BuildPageTablesIa32Pae) { AsmEnablePaging32 ( (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, HobList.Raw, NULL, (VOID *) (UINTN) TopOfStack ); } else { SwitchStack ( (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, HobList.Raw, NULL, (VOID *) (UINTN) TopOfStack ); } } }
unsigned char * WINAPI VARIANT_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar) { variant_wire_t *header; unsigned long type_size; int align; unsigned char *Pos; TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar); ALIGN_POINTER(Buffer, 7); VariantInit(pvar); header = (variant_wire_t *)Buffer; pvar->n1.n2.vt = header->vt; pvar->n1.n2.wReserved1 = header->wReserved1; pvar->n1.n2.wReserved2 = header->wReserved2; pvar->n1.n2.wReserved3 = header->wReserved3; Pos = (unsigned char*)(header + 1); type_size = get_type_size(pFlags, pvar); align = get_type_alignment(pFlags, pvar); ALIGN_POINTER(Pos, align); if(header->vt & VT_BYREF) { Pos += 4; pvar->n1.n2.n3.byref = CoTaskMemAlloc(type_size); memcpy(pvar->n1.n2.n3.byref, Pos, type_size); if((header->vt & VT_TYPEMASK) != VT_VARIANT) Pos += type_size; else Pos += 4; } else { if((header->vt & VT_TYPEMASK) == VT_DECIMAL) memcpy(pvar, Pos, type_size); else memcpy(&pvar->n1.n2.n3, Pos, type_size); Pos += type_size; } if(header->vt & VT_ARRAY) { if(header->vt & VT_BYREF) Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, V_ARRAYREF(pvar)); else Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, &V_ARRAY(pvar)); } else { switch (header->vt) { case VT_BSTR: V_BSTR(pvar) = NULL; Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar)); break; case VT_BSTR | VT_BYREF: *V_BSTRREF(pvar) = NULL; Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar)); break; case VT_VARIANT | VT_BYREF: Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar)); break; case VT_DISPATCH | VT_BYREF: FIXME("handle DISPATCH by ref\n"); break; case VT_UNKNOWN: /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */ Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, pvar); break; case VT_DISPATCH: /* this should probably call WdtpInterfacePointer_UserUnmarshal in ole32.dll */ Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, pvar); break; case VT_RECORD: FIXME("handle BRECORD by val\n"); break; case VT_RECORD | VT_BYREF: FIXME("handle BRECORD by ref\n"); break; } } return Pos; }
EFI_STATUS EFIAPI LoadDxeCoreFromFfsFile ( IN EFI_PEI_FILE_HANDLE FileHandle, IN UINTN StackSize ) { EFI_STATUS Status; VOID *PeCoffImage; EFI_PHYSICAL_ADDRESS ImageAddress; UINT64 ImageSize; EFI_PHYSICAL_ADDRESS EntryPoint; VOID *BaseOfStack; VOID *TopOfStack; VOID *Hob; EFI_FV_FILE_INFO FvFileInfo; Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &PeCoffImage); if (EFI_ERROR (Status)) { return Status; } Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint); // For NT32 Debug Status = SecWinNtPeiLoadFile (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint); ASSERT_EFI_ERROR (Status); // // Extract the DxeCore GUID file name. // Status = FfsGetFileInfo (FileHandle, &FvFileInfo); ASSERT_EFI_ERROR (Status); BuildModuleHob (&FvFileInfo.FileName, (EFI_PHYSICAL_ADDRESS)(UINTN)ImageAddress, EFI_SIZE_TO_PAGES ((UINT32) ImageSize) * EFI_PAGE_SIZE, EntryPoint); DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading DxeCore at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)EntryPoint)); Hob = GetHobList (); if (StackSize == 0) { // User the current stack ((DXE_CORE_ENTRY_POINT)(UINTN)EntryPoint) (Hob); } else { // // Allocate 128KB for the Stack // BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (StackSize)); ASSERT (BaseOfStack != NULL); // // Compute the top of the stack we were allocated. Pre-allocate a UINTN // for safety. // TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (StackSize) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT); TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); // // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. // UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, StackSize); SwitchStack ( (SWITCH_STACK_ENTRY_POINT)(UINTN)EntryPoint, Hob, NULL, TopOfStack ); } // Should never get here as DXE Core does not return DEBUG ((EFI_D_ERROR, "DxeCore returned\n")); ASSERT (FALSE); return EFI_DEVICE_ERROR; }
/** Check if an FV is consistent and allocate cache for it. @param FvDevice A pointer to the FvDevice to be checked. @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. @retval EFI_VOLUME_CORRUPTED File system is corrupted. @retval EFI_SUCCESS FV is consistent and cache is allocated. **/ EFI_STATUS FvCheck ( IN FV_DEVICE *FvDevice ) { EFI_STATUS Status; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; EFI_FVB_ATTRIBUTES_2 FvbAttributes; EFI_FV_BLOCK_MAP_ENTRY *BlockMap; EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader; UINT8 *FwCache; LBA_ENTRY *LbaEntry; FREE_SPACE_ENTRY *FreeSpaceEntry; FFS_FILE_LIST_ENTRY *FfsFileEntry; UINT8 *LbaStart; UINTN Index; EFI_LBA LbaIndex; UINT8 *Ptr; UINTN Size; UINT8 *FreeStart; UINTN FreeSize; UINT8 ErasePolarity; EFI_FFS_FILE_STATE FileState; UINT8 *TopFvAddress; UINTN TestLength; EFI_PHYSICAL_ADDRESS BaseAddress; Fvb = FvDevice->Fvb; Status = Fvb->GetAttributes (Fvb, &FvbAttributes); if (EFI_ERROR (Status)) { return Status; } InitializeListHead (&FvDevice->LbaHeader); InitializeListHead (&FvDevice->FreeSpaceHeader); InitializeListHead (&FvDevice->FfsFileListHeader); FwVolHeader = NULL; Status = GetFwVolHeader (Fvb, &FwVolHeader); if (EFI_ERROR (Status)) { return Status; } ASSERT (FwVolHeader != NULL); FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid); // // Double Check firmware volume header here // if (!VerifyFvHeaderChecksum (FwVolHeader)) { FreePool (FwVolHeader); return EFI_VOLUME_CORRUPTED; } BlockMap = FwVolHeader->BlockMap; // // FwVolHeader->FvLength is the whole FV length including FV header // FwCache = AllocateZeroPool ((UINTN) FwVolHeader->FvLength); if (FwCache == NULL) { FreePool (FwVolHeader); return EFI_OUT_OF_RESOURCES; } FvDevice->CachedFv = (EFI_PHYSICAL_ADDRESS) (UINTN) FwCache; // // Copy to memory // LbaStart = FwCache; LbaIndex = 0; Ptr = NULL; if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { // // Get volume base address // Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress); if (EFI_ERROR (Status)) { FreePool (FwVolHeader); return Status; } Ptr = (UINT8 *) ((UINTN) BaseAddress); DEBUG((EFI_D_INFO, "Fv Base Address is 0x%LX\n", BaseAddress)); } // // Copy whole FV into the memory // while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) { for (Index = 0; Index < BlockMap->NumBlocks; Index++) { LbaEntry = AllocatePool (sizeof (LBA_ENTRY)); if (LbaEntry == NULL) { FreePool (FwVolHeader); FreeFvDeviceResource (FvDevice); return EFI_OUT_OF_RESOURCES; } LbaEntry->LbaIndex = LbaIndex; LbaEntry->StartingAddress = LbaStart; LbaEntry->BlockLength = BlockMap->Length; // // Copy each LBA into memory // if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { CopyMem (LbaStart, Ptr, BlockMap->Length); Ptr += BlockMap->Length; } else { Size = BlockMap->Length; Status = Fvb->Read ( Fvb, LbaIndex, 0, &Size, LbaStart ); // // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length // if (EFI_ERROR (Status)) { FreePool (FwVolHeader); FreeFvDeviceResource (FvDevice); return Status; } } LbaIndex++; LbaStart += BlockMap->Length; InsertTailList (&FvDevice->LbaHeader, &LbaEntry->Link); } BlockMap++; } FvDevice->FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FwCache; // // it is not used any more, so free FwVolHeader // FreePool (FwVolHeader); // // Scan to check the free space & File list // if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) { ErasePolarity = 1; } else { ErasePolarity = 0; } FvDevice->ErasePolarity = ErasePolarity; // // go through the whole FV cache, check the consistence of the FV // if (FvDevice->FwVolHeader->ExtHeaderOffset != 0) { // // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists. // FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->ExtHeaderOffset); Ptr = (UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize; Ptr = (UINT8 *) ALIGN_POINTER (Ptr, 8); } else { Ptr = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->HeaderLength); } TopFvAddress = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->FvLength); // // Build FFS list & Free Space List here // while (Ptr < TopFvAddress) { TestLength = TopFvAddress - Ptr; if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { TestLength = sizeof (EFI_FFS_FILE_HEADER); } if (IsBufferErased (ErasePolarity, Ptr, TestLength)) { // // We found free space // FreeStart = Ptr; FreeSize = 0; do { TestLength = TopFvAddress - Ptr; if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { TestLength = sizeof (EFI_FFS_FILE_HEADER); } if (!IsBufferErased (ErasePolarity, Ptr, TestLength)) { break; } FreeSize += TestLength; Ptr += TestLength; } while (Ptr < TopFvAddress); FreeSpaceEntry = AllocateZeroPool (sizeof (FREE_SPACE_ENTRY)); if (FreeSpaceEntry == NULL) { FreeFvDeviceResource (FvDevice); return EFI_OUT_OF_RESOURCES; } // // Create a Free space entry // FreeSpaceEntry->StartingAddress = FreeStart; FreeSpaceEntry->Length = FreeSize; InsertTailList (&FvDevice->FreeSpaceHeader, &FreeSpaceEntry->Link); continue; } // // double check boundry // if (TestLength < sizeof (EFI_FFS_FILE_HEADER)) { break; } if (!IsValidFFSHeader ( FvDevice->ErasePolarity, (EFI_FFS_FILE_HEADER *) Ptr )) { FileState = GetFileState ( FvDevice->ErasePolarity, (EFI_FFS_FILE_HEADER *) Ptr ); if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) { if (IS_FFS_FILE2 (Ptr)) { if (!FvDevice->IsFfs3Fv) { DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name)); } Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER2); } else { Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER); } continue; } else { // // File system is corrputed, return // FreeFvDeviceResource (FvDevice); return EFI_VOLUME_CORRUPTED; } } if (IS_FFS_FILE2 (Ptr)) { ASSERT (FFS_FILE2_SIZE (Ptr) > 0x00FFFFFF); if (!FvDevice->IsFfs3Fv) { DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name)); Ptr = Ptr + FFS_FILE2_SIZE (Ptr); // // Adjust Ptr to the next 8-byte aligned boundry. // while (((UINTN) Ptr & 0x07) != 0) { Ptr++; } continue; } } if (IsValidFFSFile (FvDevice, (EFI_FFS_FILE_HEADER *) Ptr)) { FileState = GetFileState ( FvDevice->ErasePolarity, (EFI_FFS_FILE_HEADER *) Ptr ); // // check for non-deleted file // if (FileState != EFI_FILE_DELETED) { // // Create a FFS list entry for each non-deleted file // FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY)); if (FfsFileEntry == NULL) { FreeFvDeviceResource (FvDevice); return EFI_OUT_OF_RESOURCES; } FfsFileEntry->FfsHeader = Ptr; InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); } if (IS_FFS_FILE2 (Ptr)) { Ptr = Ptr + FFS_FILE2_SIZE (Ptr); } else { Ptr = Ptr + FFS_FILE_SIZE (Ptr); } // // Adjust Ptr to the next 8-byte aligned boundry. // while (((UINTN) Ptr & 0x07) != 0) { Ptr++; } } else { // // File system is corrupted, return // FreeFvDeviceResource (FvDevice); return EFI_VOLUME_CORRUPTED; } } FvDevice->CurrentFfsFile = NULL; return EFI_SUCCESS; }
unsigned char * __RPC_USER HGLOBAL_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal) { ULONG fContext; TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", pBuffer, *phGlobal); ALIGN_POINTER(pBuffer, 3); fContext = *(ULONG *)pBuffer; pBuffer += sizeof(ULONG); if (((fContext == WDT_INPROC_CALL) && (sizeof(*phGlobal) < 8)) || ((fContext == WDT_INPROC64_CALL) && (sizeof(*phGlobal) == 8))) { *phGlobal = *(HGLOBAL *)pBuffer; pBuffer += sizeof(*phGlobal); } else if (fContext == WDT_REMOTE_CALL) { ULONG handle; handle = *(ULONG *)pBuffer; pBuffer += sizeof(ULONG); if (handle) { ULONG size; void *memory; size = *(ULONG *)pBuffer; pBuffer += sizeof(ULONG); /* redundancy is bad - it means you have to check consistency like * this: */ if (*(ULONG *)pBuffer != handle) { RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL); return pBuffer; } pBuffer += sizeof(ULONG); /* redundancy is bad - it means you have to check consistency like * this: */ if (*(ULONG *)pBuffer != size) { RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL); return pBuffer; } pBuffer += sizeof(ULONG); /* FIXME: check size is not too big */ *phGlobal = GlobalAlloc(GMEM_MOVEABLE, size); memory = GlobalLock(*phGlobal); memcpy(memory, pBuffer, size); pBuffer += size; GlobalUnlock(*phGlobal); } else *phGlobal = NULL; } else RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL); return pBuffer; }
unsigned char * WINAPI LPSAFEARRAY_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa) { HRESULT hr; TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", Buffer, *ppsa); ALIGN_POINTER(Buffer, 3); *(ULONG_PTR *)Buffer = *ppsa ? TRUE : FALSE; Buffer += sizeof(ULONG_PTR); if (*ppsa) { VARTYPE vt; SAFEARRAY *psa = *ppsa; ULONG ulCellCount = SAFEARRAY_GetCellCount(psa); wireSAFEARRAY wiresa; SF_TYPE sftype; GUID guid; *(ULONG *)Buffer = psa->cDims; Buffer += sizeof(ULONG); wiresa = (wireSAFEARRAY)Buffer; wiresa->cDims = psa->cDims; wiresa->fFeatures = psa->fFeatures; wiresa->cbElements = psa->cbElements; hr = SafeArrayGetVartype(psa, &vt); if (FAILED(hr)) RpcRaiseException(hr); wiresa->cLocks = (USHORT)psa->cLocks | (vt << 16); Buffer += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs); sftype = SAFEARRAY_GetUnionType(psa); *(ULONG *)Buffer = sftype; Buffer += sizeof(ULONG); *(ULONG *)Buffer = ulCellCount; Buffer += sizeof(ULONG); *(ULONG_PTR *)Buffer = (ULONG_PTR)psa->pvData; Buffer += sizeof(ULONG_PTR); if (sftype == SF_HAVEIID) { SafeArrayGetIID(psa, &guid); memcpy(Buffer, &guid, sizeof(guid)); Buffer += sizeof(guid); } memcpy(Buffer, psa->rgsabound, sizeof(psa->rgsabound[0]) * psa->cDims); Buffer += sizeof(psa->rgsabound[0]) * psa->cDims; *(ULONG *)Buffer = ulCellCount; Buffer += sizeof(ULONG); if (psa->pvData) { switch (sftype) { case SF_BSTR: { BSTR* lpBstr; for (lpBstr = (BSTR*)psa->pvData; ulCellCount; ulCellCount--, lpBstr++) Buffer = BSTR_UserMarshal(pFlags, Buffer, lpBstr); break; } case SF_DISPATCH: case SF_UNKNOWN: case SF_HAVEIID: FIXME("marshal interfaces\n"); break; case SF_VARIANT: { VARIANT* lpVariant; for (lpVariant = (VARIANT*)psa->pvData; ulCellCount; ulCellCount--, lpVariant++) Buffer = VARIANT_UserMarshal(pFlags, Buffer, lpVariant); break; } case SF_RECORD: { IRecordInfo* pRecInfo = NULL; hr = SafeArrayGetRecordInfo(psa, &pRecInfo); if (FAILED(hr)) RpcRaiseException(hr); if (pRecInfo) { FIXME("write record info %p\n", pRecInfo); IRecordInfo_Release(pRecInfo); } break; } case SF_I8: ALIGN_POINTER(Buffer, 7); /* fallthrough */ case SF_I1: case SF_I2: case SF_I4: /* Just copy the data over */ memcpy(Buffer, psa->pvData, ulCellCount * psa->cbElements); Buffer += ulCellCount * psa->cbElements; break; default: break; } } } return Buffer; }
EFI_STATUS FvBufAddFile ( IN OUT VOID *Fv, IN VOID *File ) /*++ Routine Description: Adds a new FFS file Arguments: Fv - Address of the Fv in memory File - FFS file to add to Fv Returns: EFI_SUCCESS --*/ { EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; EFI_FFS_FILE_HEADER *fhdr = NULL; EFI_FVB_ATTRIBUTES_2 FvbAttributes; UINTN offset; UINTN fsize; UINTN newSize; UINTN clearLoop; EFI_STATUS Status; UINTN fvSize; Status = FvBufGetSize (Fv, &fvSize); if (EFI_ERROR (Status)) { return Status; } FvbAttributes = hdr->Attributes; newSize = FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)File)->Size); for( offset = (UINTN)ALIGN_POINTER (hdr->HeaderLength, 8); offset + newSize <= fvSize; offset = (UINTN)ALIGN_POINTER (offset, 8) ) { fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + offset); if (EFI_TEST_FFS_ATTRIBUTES_BIT( FvbAttributes, fhdr->State, EFI_FILE_HEADER_VALID ) ) { // BUGBUG: Need to make sure that the new file does not already // exist. fsize = FvBufExpand3ByteSize (fhdr->Size); if (fsize == 0 || (offset + fsize > fvSize)) { return EFI_VOLUME_CORRUPTED; } offset = offset + fsize; continue; } clearLoop = 0; while ((clearLoop < newSize) && (((UINT8*)fhdr)[clearLoop] == (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0) ) ) { clearLoop++; } // // We found a place in the FV which is empty and big enough for // the new file // if (clearLoop >= newSize) { break; } offset = offset + 1; // Make some forward progress } if (offset + newSize > fvSize) { return EFI_OUT_OF_RESOURCES; } CommonLibBinderCopyMem (fhdr, File, newSize); return EFI_SUCCESS; }
unsigned char * WINAPI LPSAFEARRAY_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa) { ULONG_PTR ptr; wireSAFEARRAY wiresa; ULONG cDims; HRESULT hr; SF_TYPE sftype; ULONG cell_count; GUID guid; VARTYPE vt; SAFEARRAYBOUND *wiresab; TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", Buffer, ppsa); ALIGN_POINTER(Buffer, 3); ptr = *(ULONG_PTR *)Buffer; Buffer += sizeof(ULONG_PTR); if (!ptr) { *ppsa = NULL; TRACE("NULL safe array unmarshaled\n"); return Buffer; } cDims = *(ULONG *)Buffer; Buffer += sizeof(ULONG); wiresa = (wireSAFEARRAY)Buffer; Buffer += FIELD_OFFSET(struct _wireSAFEARRAY, uArrayStructs); if (cDims != wiresa->cDims) RpcRaiseException(RPC_S_INVALID_BOUND); /* FIXME: there should be a limit on how large cDims can be */ vt = HIWORD(wiresa->cLocks); sftype = *(ULONG *)Buffer; Buffer += sizeof(ULONG); cell_count = *(ULONG *)Buffer; Buffer += sizeof(ULONG); ptr = *(ULONG_PTR *)Buffer; Buffer += sizeof(ULONG_PTR); if (sftype == SF_HAVEIID) { memcpy(&guid, Buffer, sizeof(guid)); Buffer += sizeof(guid); } wiresab = (SAFEARRAYBOUND *)Buffer; Buffer += sizeof(wiresab[0]) * wiresa->cDims; *ppsa = SafeArrayCreateEx(vt, wiresa->cDims, wiresab, NULL); if (!*ppsa) RpcRaiseException(E_OUTOFMEMORY); /* be careful about which flags we set since they could be a security * risk */ (*ppsa)->fFeatures &= FADF_AUTOSETFLAGS; (*ppsa)->fFeatures |= (wiresa->fFeatures & ~(FADF_AUTOSETFLAGS)); /* FIXME: there should be a limit on how large wiresa->cbElements can be */ (*ppsa)->cbElements = wiresa->cbElements; (*ppsa)->cLocks = LOWORD(wiresa->cLocks); hr = SafeArrayAllocData(*ppsa); if (FAILED(hr)) RpcRaiseException(hr); if ((*(ULONG *)Buffer != cell_count) || (SAFEARRAY_GetCellCount(*ppsa) != cell_count)) RpcRaiseException(RPC_S_INVALID_BOUND); Buffer += sizeof(ULONG); if (ptr) { switch (sftype) { case SF_BSTR: { BSTR* lpBstr; for (lpBstr = (BSTR*)(*ppsa)->pvData; cell_count; cell_count--, lpBstr++) Buffer = BSTR_UserUnmarshal(pFlags, Buffer, lpBstr); break; } case SF_DISPATCH: case SF_UNKNOWN: case SF_HAVEIID: FIXME("marshal interfaces\n"); break; case SF_VARIANT: { VARIANT* lpVariant; for (lpVariant = (VARIANT*)(*ppsa)->pvData; cell_count; cell_count--, lpVariant++) Buffer = VARIANT_UserUnmarshal(pFlags, Buffer, lpVariant); break; } case SF_RECORD: { FIXME("set record info\n"); break; } case SF_I8: ALIGN_POINTER(Buffer, 7); /* fallthrough */ case SF_I1: case SF_I2: case SF_I4: /* Just copy the data over */ memcpy((*ppsa)->pvData, Buffer, cell_count * (*ppsa)->cbElements); Buffer += cell_count * (*ppsa)->cbElements; break; default: break; } } TRACE("safe array unmarshaled: %p\n", *ppsa); return Buffer; }
EFI_STATUS FvBufAddVtfFile ( IN OUT VOID *Fv, IN VOID *File ) /*++ Routine Description: Adds a new FFS VFT (Volume Top File) file. In other words, adds the file to the end of the firmware volume. Arguments: Fv - Address of the Fv in memory File - FFS file to add to Fv Returns: EFI_SUCCESS --*/ { EFI_STATUS Status; EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; EFI_FFS_FILE_HEADER* NewFile; UINTN NewFileSize; UINT8 erasedUint8; UINTN clearLoop; EFI_FFS_FILE_HEADER *LastFile; UINTN LastFileSize; UINTN fvSize; UINTN Key; Status = FvBufGetSize (Fv, &fvSize); if (EFI_ERROR (Status)) { return Status; } erasedUint8 = (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0); NewFileSize = FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)File)->Size); if (NewFileSize != (UINTN)ALIGN_POINTER (NewFileSize, 8)) { return EFI_INVALID_PARAMETER; } // // Find the last file in the FV // Key = 0; LastFile = NULL; LastFileSize = 0; do { Status = FvBufFindNextFile (Fv, &Key, (VOID **)&LastFile); LastFileSize = FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)File)->Size); } while (!EFI_ERROR (Status)); // // If no files were found, then we start at the beginning of the FV // if (LastFile == NULL) { LastFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + hdr->HeaderLength); } // // We want to put the new file (VTF) at the end of the FV // NewFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + (fvSize - NewFileSize)); // // Check to see if there is enough room for the VTF after the last file // found in the FV // if ((UINT8*)NewFile < ((UINT8*)LastFile + LastFileSize)) { return EFI_OUT_OF_RESOURCES; } // // Loop to determine if the end of the FV is empty // clearLoop = 0; while ((clearLoop < NewFileSize) && (((UINT8*)NewFile)[clearLoop] == erasedUint8) ) { clearLoop++; } // // Check to see if there was not enough room for the file // if (clearLoop < NewFileSize) { return EFI_OUT_OF_RESOURCES; } CommonLibBinderCopyMem (NewFile, File, NewFileSize); return EFI_SUCCESS; }
EFI_STATUS PspP2CmboxEntry ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; //We are now in SMM //If PSP feature turn off, exit the driver if ((CheckPspDevicePresent () == FALSE) || (PcdGet8 (PcdPspPkgEnable) == 0)) { return EFI_SUCCESS; } PSP_DEBUG ("Psp.Drv.P2Cmbox Enter\n"); // // We're now in SMM! // // Init PSP storage Lib // PSP_DEBUG ("\tStorage Lib Init\n"); Status = PspStorageInit (SystemTable); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { return EFI_SUCCESS; } // Allocate SMM buffer for PSP-> BIOS communication PSP_DEBUG ("\tAllocate SMM buffer for P2C Mbox\n"); Status = gSmst->SmmAllocatePool ( EfiRuntimeServicesData, PSP_DATA_BLOCK_SIZE + 32, &PspToBiosMbox ); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { return EFI_SUCCESS; } // // Initialize the data structure ZeroMem (PspToBiosMbox, PSP_DATA_BLOCK_SIZE + 32); //Align on 32 bytes boundary PspToBiosMbox = ALIGN_POINTER ((UINTN) PspToBiosMbox, 32); PspToBiosMbox->MboxCmd = 0; *(UINT32 *)&(PspToBiosMbox->MboxSts) = MBOX_STATUS_INITIALIZED; #ifdef PSP2BIOS_USING_SW_SMI PSP_DEBUG ("\tP2C using SW SMI\n"); Status = EnablePspSwSmi (); if (EFI_ERROR (Status)) { return EFI_SUCCESS; } #else PSP_DEBUG ("\tP2C using fake SMI\n"); InitFchFakeStsInfo (&mSmmTrigInfo); Status = EnablePspFakeStsSmi (); if (EFI_ERROR (Status)) { return EFI_SUCCESS; } #endif //Get TsegBase, TsegSize LibAmdMsrRead (MSR_SMMADDR, &mTsegBase, NULL); mTsegBase &= MSR_SMMADDR_TSEGBASE_BITS; LibAmdMsrRead (MSR_SMMMASK, &mTsegSize, NULL); mTsegSize = (~(mTsegSize & MSR_SMMMASK_TSEGMASK_BITS) + 1) & MSR_SMMMASK_TSEGMASK_BITS; PSP_DEBUG ("\tSMMBase:0x%x SMMLength:0x%x\n\tPSPSmmDataRegion:0x%x PspSmmDataLength:0x%x\n", mTsegBase, mTsegSize, PspToBiosMbox, PSP_DATA_BLOCK_SIZE); //Dump mSmmTrigInfo PSP_DEBUG ("\tSmmTrigInfo::Addr:0x%x AddrType:0x%x Width:0x%x AndMask:0x%x OrMask:0x%x\n", mSmmTrigInfo.Address, mSmmTrigInfo.AddressType, mSmmTrigInfo.ValueWidth, mSmmTrigInfo.ValueAndMask, mSmmTrigInfo.ValueOrMask); if (PspMboxBiosCmdSmmInfo ( mTsegBase, mTsegSize, (UINT64) PspToBiosMbox, PSP_DATA_BLOCK_SIZE, &mSmmTrigInfo )) { return (EFI_SUCCESS); } PSP_DEBUG ("P2Cmbox Exit\n"); return EFI_SUCCESS; }
EFI_STATUS FvBufFindNextFile ( IN VOID *Fv, IN OUT UINTN *Key, OUT VOID **File ) /*++ Routine Description: Iterates through the files contained within the firmware volume Arguments: Fv - Address of the Fv in memory Key - Should be 0 to get the first file. After that, it should be passed back in without modifying it's contents to retrieve subsequent files. File - Output file pointer File == NULL - invalid parameter otherwise - *File will be update to the location of the file Returns: EFI_SUCCESS EFI_NOT_FOUND EFI_VOLUME_CORRUPTED --*/ { EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; EFI_FFS_FILE_HEADER *fhdr = NULL; EFI_FVB_ATTRIBUTES_2 FvbAttributes; UINTN fsize; EFI_STATUS Status; UINTN fvSize; if (Fv == NULL) { return EFI_INVALID_PARAMETER; } Status = FvBufGetSize (Fv, &fvSize); if (EFI_ERROR (Status)) { return Status; } if (*Key == 0) { *Key = hdr->HeaderLength; } FvbAttributes = hdr->Attributes; for( *Key = (UINTN)ALIGN_POINTER (*Key, 8); (*Key + sizeof (*fhdr)) < fvSize; *Key = (UINTN)ALIGN_POINTER (*Key, 8) ) { fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + *Key); fsize = FvBufExpand3ByteSize (fhdr->Size); if (!EFI_TEST_FFS_ATTRIBUTES_BIT( FvbAttributes, fhdr->State, EFI_FILE_HEADER_VALID ) || EFI_TEST_FFS_ATTRIBUTES_BIT( FvbAttributes, fhdr->State, EFI_FILE_HEADER_INVALID ) ) { *Key = *Key + 1; // Make some forward progress continue; } else if( EFI_TEST_FFS_ATTRIBUTES_BIT( FvbAttributes, fhdr->State, EFI_FILE_MARKED_FOR_UPDATE ) || EFI_TEST_FFS_ATTRIBUTES_BIT( FvbAttributes, fhdr->State, EFI_FILE_DELETED ) ) { *Key = *Key + fsize; continue; } else if (EFI_TEST_FFS_ATTRIBUTES_BIT( FvbAttributes, fhdr->State, EFI_FILE_DATA_VALID ) ) { *File = (UINT8*)hdr + *Key; *Key = *Key + fsize; return EFI_SUCCESS; } *Key = *Key + 1; // Make some forward progress } return EFI_NOT_FOUND; }
/** Check if an FV is consistent and allocate cache for it. @param FvDevice A pointer to the FvDevice to be checked. @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. @retval EFI_SUCCESS FV is consistent and cache is allocated. @retval EFI_VOLUME_CORRUPTED File system is corrupted. **/ EFI_STATUS FvCheck ( IN OUT FV_DEVICE *FvDevice ) { EFI_STATUS Status; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader; EFI_FVB_ATTRIBUTES_2 FvbAttributes; EFI_FV_BLOCK_MAP_ENTRY *BlockMap; FFS_FILE_LIST_ENTRY *FfsFileEntry; EFI_FFS_FILE_HEADER *FfsHeader; UINT8 *CacheLocation; UINTN LbaOffset; UINTN HeaderSize; UINTN Index; EFI_LBA LbaIndex; UINTN Size; EFI_FFS_FILE_STATE FileState; UINT8 *TopFvAddress; UINTN TestLength; EFI_PHYSICAL_ADDRESS PhysicalAddress; BOOLEAN FileCached; UINTN WholeFileSize; EFI_FFS_FILE_HEADER *CacheFfsHeader; FileCached = FALSE; CacheFfsHeader = NULL; Fvb = FvDevice->Fvb; FwVolHeader = FvDevice->FwVolHeader; Status = Fvb->GetAttributes (Fvb, &FvbAttributes); if (EFI_ERROR (Status)) { return Status; } // // Size is the size of the FV minus the head. We have already allocated // the header to check to make sure the volume is valid // Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength); if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { FvDevice->IsMemoryMapped = TRUE; Status = Fvb->GetPhysicalAddress (Fvb, &PhysicalAddress); if (EFI_ERROR (Status)) { return Status; } // // Don't cache memory mapped FV really. // FvDevice->CachedFv = (UINT8 *) (UINTN) (PhysicalAddress + FwVolHeader->HeaderLength); } else { FvDevice->IsMemoryMapped = FALSE; FvDevice->CachedFv = AllocatePool (Size); if (FvDevice->CachedFv == NULL) { return EFI_OUT_OF_RESOURCES; } } // // Remember a pointer to the end fo the CachedFv // FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size; if (!FvDevice->IsMemoryMapped) { // // Copy FV minus header into memory using the block map we have all ready // read into memory. // BlockMap = FwVolHeader->BlockMap; CacheLocation = FvDevice->CachedFv; LbaIndex = 0; LbaOffset = 0; HeaderSize = FwVolHeader->HeaderLength; while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) { Index = 0; Size = BlockMap->Length; if (HeaderSize > 0) { // // Skip header size // for (; Index < BlockMap->NumBlocks && HeaderSize >= BlockMap->Length; Index ++) { HeaderSize -= BlockMap->Length; LbaIndex ++; } // // Check whether FvHeader is crossing the multi block range. // if (Index >= BlockMap->NumBlocks) { BlockMap++; continue; } else if (HeaderSize > 0) { LbaOffset = HeaderSize; Size = BlockMap->Length - HeaderSize; HeaderSize = 0; } } // // read the FV data // for (; Index < BlockMap->NumBlocks; Index ++) { Status = Fvb->Read (Fvb, LbaIndex, LbaOffset, &Size, CacheLocation ); // // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length // if (EFI_ERROR (Status)) { goto Done; } LbaIndex++; CacheLocation += Size; // // After we skip Fv Header always read from start of block // LbaOffset = 0; Size = BlockMap->Length; } BlockMap++; } } // // Scan to check the free space & File list // if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) { FvDevice->ErasePolarity = 1; } else { FvDevice->ErasePolarity = 0; } // // go through the whole FV cache, check the consistence of the FV. // Make a linked list of all the Ffs file headers // Status = EFI_SUCCESS; InitializeListHead (&FvDevice->FfsFileListHeader); // // Build FFS list // if (FwVolHeader->ExtHeaderOffset != 0) { // // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists. // FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (FvDevice->CachedFv + (FwVolHeader->ExtHeaderOffset - FwVolHeader->HeaderLength)); FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize); FfsHeader = (EFI_FFS_FILE_HEADER *) ALIGN_POINTER (FfsHeader, 8); } else { FfsHeader = (EFI_FFS_FILE_HEADER *) (FvDevice->CachedFv); } TopFvAddress = FvDevice->EndOfCachedFv; while (((UINTN) FfsHeader >= (UINTN) FvDevice->CachedFv) && ((UINTN) FfsHeader <= (UINTN) ((UINTN) TopFvAddress - sizeof (EFI_FFS_FILE_HEADER)))) { if (FileCached) { CoreFreePool (CacheFfsHeader); FileCached = FALSE; } TestLength = TopFvAddress - ((UINT8 *) FfsHeader); if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { TestLength = sizeof (EFI_FFS_FILE_HEADER); } if (IsBufferErased (FvDevice->ErasePolarity, FfsHeader, TestLength)) { // // We have found the free space so we are done! // goto Done; } if (!IsValidFfsHeader (FvDevice->ErasePolarity, FfsHeader, &FileState)) { if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) { if (IS_FFS_FILE2 (FfsHeader)) { if (!FvDevice->IsFfs3Fv) { DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsHeader->Name)); } FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2)); } else { FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER)); } continue; } else { // // File system is corrputed // Status = EFI_VOLUME_CORRUPTED; goto Done; } } CacheFfsHeader = FfsHeader; if ((CacheFfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) { if (FvDevice->IsMemoryMapped) { // // Memory mapped FV has not been cached. // Here is to cache FFS file to memory buffer for following checksum calculating. // And then, the cached file buffer can be also used for FvReadFile. // WholeFileSize = IS_FFS_FILE2 (CacheFfsHeader) ? FFS_FILE2_SIZE (CacheFfsHeader): FFS_FILE_SIZE (CacheFfsHeader); CacheFfsHeader = AllocateCopyPool (WholeFileSize, CacheFfsHeader); if (CacheFfsHeader == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } FileCached = TRUE; } } if (!IsValidFfsFile (FvDevice->ErasePolarity, CacheFfsHeader)) { // // File system is corrupted // Status = EFI_VOLUME_CORRUPTED; goto Done; } if (IS_FFS_FILE2 (CacheFfsHeader)) { ASSERT (FFS_FILE2_SIZE (CacheFfsHeader) > 0x00FFFFFF); if (!FvDevice->IsFfs3Fv) { DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &CacheFfsHeader->Name)); FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader)); // // Adjust pointer to the next 8-byte aligned boundry. // FfsHeader = (EFI_FFS_FILE_HEADER *) (((UINTN) FfsHeader + 7) & ~0x07); continue; } } FileState = GetFileState (FvDevice->ErasePolarity, CacheFfsHeader); // // check for non-deleted file // if (FileState != EFI_FILE_DELETED) { // // Create a FFS list entry for each non-deleted file // FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY)); if (FfsFileEntry == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } FfsFileEntry->FfsHeader = CacheFfsHeader; FfsFileEntry->FileCached = FileCached; FileCached = FALSE; InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); } if (IS_FFS_FILE2 (CacheFfsHeader)) { FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader)); } else { FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE_SIZE (CacheFfsHeader)); } // // Adjust pointer to the next 8-byte aligned boundry. // FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINTN)FfsHeader + 7) & ~0x07); } Done: if (EFI_ERROR (Status)) { if (FileCached) { CoreFreePool (CacheFfsHeader); FileCached = FALSE; } FreeFvDeviceResource (FvDevice); } return Status; }
/** ImageRead function that operates on a memory buffer whos base is passed into FileHandle. @param Reloc Ponter to baes of the input stream @param Fixup Offset to the start of the buffer @param FixupData Number of bytes to copy into the buffer @param Adjust Location to place results of read @retval RETURN_SUCCESS Data is read from FileOffset from the Handle into the buffer. **/ RETURN_STATUS GluePeHotRelocateImageEx ( IN UINT16 *Reloc, IN OUT CHAR8 *Fixup, IN OUT CHAR8 **FixupData, IN UINT64 Adjust ) { UINT64 *F64; UINT64 FixupVal; switch ((*Reloc) >> 12) { case EFI_IMAGE_REL_BASED_DIR64: F64 = (UINT64 *) Fixup; *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64)); if (*(UINT64 *) (*FixupData) == *F64) { *F64 = *F64 + (UINT64) Adjust; } *FixupData = *FixupData + sizeof (UINT64); break; case EFI_IMAGE_REL_BASED_IA64_IMM64: F64 = (UINT64 *) Fixup; *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64)); if (*(UINT64 *) (*FixupData) == *F64) { // // Align it to bundle address before fixing up the // 64-bit immediate value of the movl instruction. // // Fixup = (CHAR8 *) ((UINT64) Fixup & (UINT64)~(15)); FixupVal = (UINT64) 0; // // Extract the lower 32 bits of IMM64 from bundle // EXT_IMM64 ( FixupVal, (UINT32 *) Fixup + IMM64_IMM7B_INST_WORD_X, IMM64_IMM7B_SIZE_X, IMM64_IMM7B_INST_WORD_POS_X, IMM64_IMM7B_VAL_POS_X ); EXT_IMM64 ( FixupVal, (UINT32 *) Fixup + IMM64_IMM9D_INST_WORD_X, IMM64_IMM9D_SIZE_X, IMM64_IMM9D_INST_WORD_POS_X, IMM64_IMM9D_VAL_POS_X ); EXT_IMM64 ( FixupVal, (UINT32 *) Fixup + IMM64_IMM5C_INST_WORD_X, IMM64_IMM5C_SIZE_X, IMM64_IMM5C_INST_WORD_POS_X, IMM64_IMM5C_VAL_POS_X ); EXT_IMM64 ( FixupVal, (UINT32 *) Fixup + IMM64_IC_INST_WORD_X, IMM64_IC_SIZE_X, IMM64_IC_INST_WORD_POS_X, IMM64_IC_VAL_POS_X ); EXT_IMM64 ( FixupVal, (UINT32 *) Fixup + IMM64_IMM41a_INST_WORD_X, IMM64_IMM41a_SIZE_X, IMM64_IMM41a_INST_WORD_POS_X, IMM64_IMM41a_VAL_POS_X ); // // Update 64-bit address // FixupVal += Adjust; // // Insert IMM64 into bundle // INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IMM7B_INST_WORD_X), IMM64_IMM7B_SIZE_X, IMM64_IMM7B_INST_WORD_POS_X, IMM64_IMM7B_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IMM9D_INST_WORD_X), IMM64_IMM9D_SIZE_X, IMM64_IMM9D_INST_WORD_POS_X, IMM64_IMM9D_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IMM5C_INST_WORD_X), IMM64_IMM5C_SIZE_X, IMM64_IMM5C_INST_WORD_POS_X, IMM64_IMM5C_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IC_INST_WORD_X), IMM64_IC_SIZE_X, IMM64_IC_INST_WORD_POS_X, IMM64_IC_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IMM41a_INST_WORD_X), IMM64_IMM41a_SIZE_X, IMM64_IMM41a_INST_WORD_POS_X, IMM64_IMM41a_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IMM41b_INST_WORD_X), IMM64_IMM41b_SIZE_X, IMM64_IMM41b_INST_WORD_POS_X, IMM64_IMM41b_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IMM41c_INST_WORD_X), IMM64_IMM41c_SIZE_X, IMM64_IMM41c_INST_WORD_POS_X, IMM64_IMM41c_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_SIGN_INST_WORD_X), IMM64_SIGN_SIZE_X, IMM64_SIGN_INST_WORD_POS_X, IMM64_SIGN_VAL_POS_X ); *(UINT64 *) (*FixupData) = *F64; } *FixupData = *FixupData + sizeof (UINT64); break; default: DEBUG ((EFI_D_ERROR, "PeHotRelocateEx:unknown fixed type\n")); return RETURN_UNSUPPORTED; } return RETURN_SUCCESS; }