UEFI本身不支持多线程,据说主要原因是:UEFI设计本身是为了启动硬件,做一些比较简单的事情,如果支持多线程会使得设计复杂度直线上升,出现问题也不容易调试。
不过UEFI本身是有对应的Protocol 的,称作 EFI_MP_SERVICES_PROTOCOL 。 具体的这个 Protocol 可以在 PI spec 中找到(UEFI Spec中没有)。下面来自【参考1】
同样可以作为参考的还有EFI_Toolkit_2.0.0.1 中的process.c 程序。
程序很简单,首先 LocateProtocol 到EFI_MP_SERVICES_PROTOCOL。然后,用 Protocol 提供的EFI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS 和EFI_MP_SERVICES_GET_PROCESSOR_INFO 来获得关于处理器的一些信息。需要注意的是EFI_MP_SERVICES_GET_PROCESSOR_INFO,输入的参数ProcessorNumber 意思是:当前要获得的 Processor 号,输入0 表示你要去的编号为 0 的Processor 的信息,输入3 表示你要去的编号为 3 的Processor 的信息,取值范围从0到NumberOfProcessors -1。
最终的代码:
#include <Uefi.h> #include <Library/UefiLib.h> #include <Library/ShellCEntryLib.h> #include <Pi/PiDxeCis.h> #include <Protocol/MpService.h> EFI_GUID gEfiMpServiceProtocolGuid = { 0x3fdda605, 0xa76e, 0x4f46, { 0xad, 0x29, 0x12, 0xf4, 0x53, 0x1b, 0x3d, 0x08 }}; extern EFI_BOOT_SERVICES *gBS; int EFIAPI main ( IN int Argc, IN CHAR16 **Argv ) { EFI_STATUS Status; EFI_MP_SERVICES_PROTOCOL *MP=NULL; UINTN i; UINTN NumProcessors; UINTN NumberOfEnabledProcessors; EFI_PROCESSOR_INFORMATION ProcessorInfo; //Get MP_Service Protocol Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID**)&MP); if (EFI_ERROR (Status)) { Print(L"Unable to initialize MP protocol interface!"); return EFI_UNSUPPORTED; } // Determine number of processors Status = MP->GetNumberOfProcessors( MP, &NumProcessors , &NumberOfEnabledProcessors ); if (EFI_ERROR (Status)) { Print( L"MP->GetNumEnabledProcessors:Unable to determine number of processors\n") ; return EFI_UNSUPPORTED; } Print(L"Number of Processors %d\n",NumProcessors); Print(L"Number of Enabled Processors %d\n",NumberOfEnabledProcessors); //Get more information by GetProcessorInfo for (i=0;i<NumProcessors;i++) { Status = MP->GetProcessorInfo(MP, i , &ProcessorInfo); Print( L"Prcoessor #%d ACPI Processor ID = %lX, Flags = %x, Package = %x, Core = %x, Thread = %x \n", i, ProcessorInfo.ProcessorId, ProcessorInfo.StatusFlag, ProcessorInfo.Location.Package, ProcessorInfo.Location.Core, ProcessorInfo.Location.Thread); } return EFI_SUCCESS; }
运行结果:
完整的代码下载:
关于这部分程序,在《UEFI 原理与编程》第13章 深入了解多任务 有更详细的论述,如果你有这方面的需求,推荐直接阅读。
另外,如果你想获得更多CPU方面的信息,比如 Cache大小, 还可以通过 CPUID,但是非常不建议通过 SMBIOS 来获得,因为他并不可靠......
最后特别提醒:
开始编写程序时,我遇到了下面的错误,错误代码对于解决问题毫无帮助,最后经过分析发现是因为没有添加PiDxe.h头文件(感谢Marco指出)导致的。
c:\edk\MdePkg\Include\Protocol/MpService.h(361) : error C2146: syntax error : missing ')' before identifier 'Procedure'
c:\edk\MdePkg\Include\Protocol/MpService.h(361) : error C2081: 'EFI_AP_PROCEDURE' : name in formal parameter list illegal
c:\edk\MdePkg\Include\Protocol/MpService.h(361) : error C2061: syntax error : identifier 'Procedure'
c:\edk\MdePkg\Include\Protocol/MpService.h(361) : error C2059: syntax error : ';'
c:\edk\MdePkg\Include\Protocol/MpService.h(361) : error C2059: syntax error : ','
c:\edk\MdePkg\Include\Protocol/MpService.h(367) : error C2059: syntax error : ')'
c:\edk\MdePkg\Include\Protocol/MpService.h(459) : error C2146: syntax error : missing ')' before identifier 'Procedure'
c:\edk\MdePkg\Include\Protocol/MpService.h(459) : error C2081: 'EFI_AP_PROCEDURE' : name in formal parameter list illegal
c:\edk\MdePkg\Include\Protocol/MpService.h(459) : error C2061: syntax error : identifier 'Procedure'
c:\edk\MdePkg\Include\Protocol/MpService.h(459) : error C2059: syntax error : ';'
c:\edk\MdePkg\Include\Protocol/MpService.h(459) : error C2059: syntax error : ','
c:\edk\MdePkg\Include\Protocol/MpService.h(465) : error C2059: syntax error : ')'
c:\edk\MdePkg\Include\Protocol/MpService.h(623) : error C2061: syntax error : identifier 'EFI_MP_SERVICES_STARTUP_ALL_APS'
c:\edk\MdePkg\Include\Protocol/MpService.h(624) : error C2061: syntax error : identifier 'StartupThisAP'
c:\edk\MdePkg\Include\Protocol/MpService.h(624) : error C2059: syntax error : ';'
c:\edk\MdePkg\Include\Protocol/MpService.h(628) : error C2059: syntax error : '}'
NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 9.0\Vc\bin\cl.exe"' : return code '0x2'
Stop.
参考:
1. Vol2_DXE CIS_1_3.pdf P174
因为缺少了PiDxe.h这个头文件,所以才报的问题。
谢谢哈,我补充上。
Hello
First let me thank you for your work and examples.
Second,I don't know any programming language so I ask for help.
Try to build x64 version but no luck yet.
Used Ubuntu few version (14 16 and 18) and few version of EDK2 but allway get these errors.
For two of them I find a workaround but one still remain.
Can you provide a fix?
Thankyou.
Library error
error 4000: Instance of library class [LibC] is not found
in [/home/G62/src/edk2/MPTest1/MPTest1.inf] [X64]
-solved by adding "!include StdLib\StdLib.inc"
main error
/home/G62/src/edk2/MPTest1/MPTest1.c:14:1: error: second argument of ‘main’ should be ‘char **’ [-Werror=main]
main ( ...
return EFI_UNSUPPORTED error
/home/G62/src/edk2/MdePkg/Include/Base.h:927:38: error: overflow in implicit constant conversion [-Werror=overflow]
#define ENCODE_ERROR(StatusCode) ((RETURN_STATUS)(MAX_BIT | (StatusCode)))
-quick fix replaced return EFI_UNSUPPORTED with return EFI_SUCCESS
Hi,
My suggestion is to build with Windows + VS2015, eg: you can install a virtualbox under Ubuntu.
As EDK2 is developed with Windows Tools Chain, it would get errors when you switch to Linux enviroment.
And you can try latest release https://github.com/tianocore/edk2/releases/tag/edk2-stable202002 .
It may have better support for Linux.
Hello again
Thanks for answer.
Indeed under windows works.
But my HP laptop Insyde 3.5 BIOS use an deprecated protocol
FRAMEWORK_EFI_MP_SERVICES_PROTOCOL_GUID:[0xf33261e7, 0x23cb, 0x11d5, 0xbd, 0x5c, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81]
Using your code as template I made this,don't know if is correct but result is
Number of Processors 4
Max number of Processors 8
Number of Enabled Processors 4
RendezvousIntNumber 0
RendezvousProcLength 4096
Processor #0 ACPI Apic ID = 0, Enabled = 1, Designation = 1, Health = 0, PackageNumber = 0, NumberOfCores = 8, NumberOfThreads = 2, ProcessorPALCompatibilityFlags = 2, ProcessorTestMask = 0
Processor #1 ACPI Apic ID = 1, Enabled = 1, Designation = 0, Health = 0, PackageNumber = 0, NumberOfCores = 8, NumberOfThreads = 2, ProcessorPALCompatibilityFlags = 2, ProcessorTestMask = 0
Processor #2 ACPI Apic ID = 4, Enabled = 1, Designation = 0, Health = 0, PackageNumber = 0, NumberOfCores = 8, NumberOfThreads = 2, ProcessorPALCompatibilityFlags = 2, ProcessorTestMask = 0
Processor #3 ACPI Apic ID = 5, Enabled = 1, Designation = 0, Health = 0, PackageNumber = 0, NumberOfCores = 8, NumberOfThreads = 2, ProcessorPALCompatibilityFlags = 2, ProcessorTestMask = 0
I did something wrong since it say 8 cores.
On some generation of HP laptops there is a problem with some OS, doesn't detect right all cores and complain about LAPIC,So I try to investigate what's the problem not all cores enabled by BIOS or LAPIC doesn't configured properly.
Here is what I did
#include
#include
#include
#include
#include
EFI_GUID gFrameworkEfiMpServiceProtocolGuid = { 0xf33261e7, 0x23cb, 0x11d5,
{ 0xbd, 0x5c, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 }};
extern EFI_BOOT_SERVICES *gBS;
int
EFIAPI
main (
IN int Argc,
IN CHAR16 **Argv
)
{
EFI_STATUS Status;
FRAMEWORK_EFI_MP_SERVICES_PROTOCOL *MP=NULL;
UINTN i;
UINTN NumberOfCPUs;
UINTN NumberOfEnabledCPUs;
UINTN BufferLenght;
UINTN MaximumNumberOfCPUs;
UINTN RendezvousIntNumber;
UINTN RendezvousProcLength;
EFI_MP_PROC_CONTEXT ProcessorContextBuffer;
//Get MP_Service Protocol
Status = gBS->LocateProtocol (&gFrameworkEfiMpServiceProtocolGuid, NULL, (VOID**)&MP);
if (EFI_ERROR (Status)) {
Print(L"Unable to initialize MP protocol interface!");
return EFI_UNSUPPORTED;
}
// Determine number of processors
Status = MP->GetGeneralMPInfo( MP, &NumberOfCPUs , &MaximumNumberOfCPUs , &NumberOfEnabledCPUs , &RendezvousIntNumber , &RendezvousProcLength );
if (EFI_ERROR (Status))
{
Print( L"MP->GetNumEnabledProcessors:Unable to determine number of processors\n") ;
return EFI_UNSUPPORTED;
}
Print(L"Number of Processors %d\n",NumberOfCPUs);
Print(L"Max number of Processors %d\n",MaximumNumberOfCPUs);
Print(L"Number of Enabled Processors %d\n",NumberOfEnabledCPUs);
Print(L"RendezvousIntNumber %d\n",RendezvousIntNumber);
Print(L"RendezvousProcLength %d\n",RendezvousProcLength);
//Get more information by GetProcessorContext
for (i=0;iGetProcessorContext(MP, i , &BufferLenght , &ProcessorContextBuffer);
Print( L"Processor #%d ACPI Apic ID = %lX, Enabled = %x, Designation = %x, Health = %x, PackageNumber = %x, NumberOfCores = %x, NumberOfThreads = %x, ProcessorPALCompatibilityFlags = %x, ProcessorTestMask = %x \n",
i,
ProcessorContextBuffer.ApicID,
ProcessorContextBuffer.Enabled,
ProcessorContextBuffer.Designation,
ProcessorContextBuffer.Health,
ProcessorContextBuffer.PackageNumber,
ProcessorContextBuffer.NumberOfCores,
ProcessorContextBuffer.NumberOfThreads,
ProcessorContextBuffer.ProcessorPALCompatibilityFlags,
ProcessorContextBuffer.ProcessorTestMask);
}
return EFI_SUCCESS;
}
You can compare the test result with CPU-z under OS. BIOS may be return an error result as this Protocol is not an important one.
And if you just want to get the number of CPU cores, you may study the usage of CPUID.
#include
#include
#include
#include
#include
Seem like some parts of text doesn't appear in previous message.
Anyway if this get same result I write again. what is at include
Uefi.h
Library/UefiLib.h
Library/ShellCEntryLib.h
Pi/PiDxeCis.h
Include/Protocol/FrameworkMpService.h
今天刚遇到了和博主同样的问题,当时无奈只得将APP改为DXE才能编过。终于在这就得到答案了。感谢博主,又学习了。
感謝博主分享,
在.c 中
EFI_GUID gEfiMpServiceProtocolGuid = {0x3fdda605, 0xa76e, 0x4f46, {0xad, 0x29, 0x12, 0xf4, 0x53, 0x1b, 0x3d, 0x08}}; 這個GUID 可以在.inf 中宣告即可:
[Protocols]
gEfiMpServiceProtocolGuid
這個 GUID 已經在 MdePkg.dec 中定義,而 MdePkg 已包在 .inf 的 packages 中
学习了,谢谢!