一.EDKII实现代码
.c文件:
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/SimpleFileSystem.h>
#include <Guid/FileInfo.h>
#include <Library/BmpSupportLib.h>
#include <IndustryStandard/Bmp.h>
#include <Library/MemoryAllocationLib.h>
typedef struct
{
EFI_PHYSICAL_ADDRESS FrameBufferBase;
UINTN FrameBufferSize;
UINT32 HorizontalResolution;
UINT32 VerticalResolution;
UINT32 PixelsPerScanLine;
} VIDEO_CONFIG;
VIDEO_CONFIG VideoConfig = {0};
EFI_STATUS
EFIAPI
UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
EFI_STATUS Status = EFI_SUCCESS;
UINTN NumHandles = 0;
EFI_HANDLE *Buffer = NULL;
/********************** 1.显示配置 *************************/
Status = gBS->LocateHandleBuffer(
ByProtocol,
&gEfiGraphicsOutputProtocolGuid,
NULL,
&NumHandles,
&Buffer
);
Print(L"Status = %d.\n", Status);
if(EFI_ERROR(Status)) {
Print(L"Failed to LocateHandleBuffer.\n");
return Status;
}
Print(L"Hello Protocol.\n");
Print(L"NumHandles = %d.\n", NumHandles);
EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
Status = gBS->OpenProtocol(
Buffer[0],
&gEfiGraphicsOutputProtocolGuid,
(void **)&Gop,
ImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if(EFI_ERROR(Status))
{
Print(L"Failed to OpenProtocol\n");
}
UINTN SizeofInfo = 0;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
for(UINTN i = 0; i < Gop->Mode->MaxMode; i++)
{
Status = Gop->QueryMode(
Gop,
i,
&SizeofInfo,
&Info
);
if(EFI_ERROR(Status))
{
Print(L"Failed To QueryMode.\n");
return Status;
}
Print(L"Mode = %d, H = %d, V = %d.\n",
i,
Info->HorizontalResolution,
Info->VerticalResolution);
}
Status = Gop->SetMode(Gop, 18); // 1440 * 900
if(EFI_ERROR(Status))
{
Print(L"Failed to SetMode.\n");
return Status;
}
VideoConfig.FrameBufferBase = Gop->Mode->FrameBufferBase;
VideoConfig.FrameBufferSize = Gop->Mode->FrameBufferSize;
VideoConfig.HorizontalResolution = Gop->Mode->Info->HorizontalResolution;
VideoConfig.VerticalResolution = Gop->Mode->Info->VerticalResolution;
VideoConfig.PixelsPerScanLine = Gop->Mode->Info->PixelsPerScanLine;
Print(L"FrameBufferBase=%llx\n", Gop->Mode->FrameBufferBase);
/************************** 2.文件系统配置 ******************************/
Status = gBS->LocateHandleBuffer(
ByProtocol,
&gEfiSimpleFileSystemProtocolGuid,
NULL,
&NumHandles,
&Buffer
);
if(EFI_ERROR(Status))
{
Print(L"Failed to LocateHandleBuffer.\n");
return Status;
}
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
Status = gBS->OpenProtocol(
Buffer[0],
&gEfiSimpleFileSystemProtocolGuid,
(VOID **)&FileSystem,
ImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if(EFI_ERROR(Status))
{
Print(L"Failed to OpenProtocol.\n");
return Status;
}
EFI_FILE_PROTOCOL *Root;
Status = FileSystem->OpenVolume(
FileSystem,
&Root
);
if(EFI_ERROR(Status))
{
Print(L"Failed to OpenVolume.\n");
return Status;
}
CHAR16 *FileName = L"\\Logo.BMP";
EFI_FILE_PROTOCOL *LogoHandle;
Status = Root->Open(
Root,
&LogoHandle,
FileName, // L"\\Logo.bmp"
EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if(EFI_ERROR(Status))
{
Print(L"Failed to Open.\n");
return Status;
}
/************************** 3.将logo文件数据读到内存 ******************************/
/* a.获取文件大小等信息 */
EFI_FILE_INFO *BmpFileInfo;
UINTN InfoSize = sizeof(EFI_FILE_INFO) + StrLen(FileName) * 2;
Status = gBS->AllocatePool(
EfiLoaderData,
InfoSize,
(VOID **)&BmpFileInfo
);
if(EFI_ERROR(Status))
{
Print(L"Failed to AllocatePool.\n");
return Status;
}
Status = LogoHandle->GetInfo(
LogoHandle,
&gEfiFileInfoGuid,
&InfoSize,
BmpFileInfo
);
if(EFI_ERROR(Status))
{
Print(L"Failed to GetInfo %d.\n", Status);
return Status;
}
/* b.根据文件大小申请内存,存放文件数据 */
UINT8 * FileBufferAddress;
FileBufferAddress = (UINT8 *)AllocateZeroPool (BmpFileInfo->FileSize);
/* c.读取文件数据到申请的内存 */
UINTN BmpSize = BmpFileInfo->FileSize;
Status = LogoHandle->Read(
LogoHandle,
&BmpSize,
(VOID *)FileBufferAddress
);
if(EFI_ERROR(Status))
{
Print(L"Failed to Read.\n");
return Status;
}
/* d.将图形数据转换成blt */
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EepromBitmap = NULL;
UINTN GopBltSize;
UINTN Height;
UINTN Width;
Status = TranslateBmpToGopBlt (
(VOID *)FileBufferAddress,
BmpSize,
&EepromBitmap,
&GopBltSize,
&Height,
&Width
);
if(EFI_ERROR(Status))
{
if (EepromBitmap != NULL)
FreePool (EepromBitmap);
Print(L"Failed to Blt Logo. %d\n", Status);
return Status;
}
Status = Gop->Blt (
Gop,
EepromBitmap,
EfiBltBufferToVideo,
0,
0,
0x0,
0x0,
Width,
Height,
Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
if (EFI_ERROR (Status)) {
Print (L"GraphicsOutput Blt is error!\n");
return Status;
}
if (EepromBitmap != NULL)
FreePool (EepromBitmap);
FreePool(FileBufferAddress); //释放存放logo file的buffer
gBS->FreePool(BmpFileInfo);
Status = LogoHandle->Close(LogoHandle);
if(EFI_ERROR(Status))
{
Print(L"Failed to close LogoHandle.\n");
return Status;
}
/************************** 4.将Kernel.bin文件数据读到内存 ******************************/
FileName = L"\\Kernel.bin";
EFI_FILE_PROTOCOL *KernelHandle;
Status = Root->Open(
Root,
&KernelHandle,
FileName,
EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if(EFI_ERROR(Status))
{
Print(L"Failed to Open.\n");
return Status;
}
EFI_FILE_INFO *KernelFileInfo;
InfoSize = sizeof(EFI_FILE_INFO) + StrLen(FileName) * 2;
Status = gBS->AllocatePool(
EfiLoaderData,
InfoSize,
(VOID **)&KernelFileInfo
);
if(EFI_ERROR(Status))
{
Print(L"Failed to AllocatePool.\n");
return Status;
}
Status = KernelHandle->GetInfo(
KernelHandle,
&gEfiFileInfoGuid,
&InfoSize,
KernelFileInfo
);
if(EFI_ERROR(Status))
{
Print(L"Failed to GetInfo %d.\n", Status);
return Status;
}
FileBufferAddress = (UINT8 *)AllocateZeroPool (KernelFileInfo->FileSize);
UINTN KernelSize = KernelFileInfo->FileSize;
Status = KernelHandle->Read(
KernelHandle,
&KernelSize,
(VOID *)FileBufferAddress
);
if(EFI_ERROR(Status))
{
return Status;
}
/************************** 5.资源释放 ******************************/
gBS->FreePool(KernelFileInfo);
Status = KernelHandle->Close(KernelHandle);
if(EFI_ERROR(Status))
{
Print(L"Failed to close KernelHandle.\n");
return Status;
}
Status = Root->Close(Root);
if(EFI_ERROR(Status))
{
Print(L"Failed to Read.\n");
return Status;
}
/************************** 6.关闭BOOT SERVICE ******************************/
typedef struct
{
UINTN BufferSize;
VOID *Buffer;
UINTN MapSize;
UINTN MapKey;
UINTN DescriptorSize;
UINT32 DescriptorVersion;
} MEMORY_MAP;
MEMORY_MAP MemMap = {4096 * 4, NULL,4096,0,0,0};
Status = gBS->AllocatePool(
EfiLoaderData,
MemMap.BufferSize,
&MemMap.Buffer
);
if(EFI_ERROR(Status))
{
Print(L"Allocate pool for memory map failed.\n");
return Status;
}
Status = gBS->GetMemoryMap(
&MemMap.BufferSize,
(EFI_MEMORY_DESCRIPTOR *)MemMap.Buffer,
&MemMap.MapKey,
&MemMap.DescriptorSize,
&MemMap.DescriptorVersion
);
if(EFI_ERROR(Status))
{
Print(L"Get memory map error.\n");
return Status;
}
Status = gBS->ExitBootServices(
ImageHandle, MemMap.MapKey
);
if(EFI_ERROR(Status))
{
Print(L"ExitBootServices error.\n");
return Status;
}
/************************** 7.跳转到操作系统运行 ******************************/
asm("jmp %0": : "m"(FileBufferAddress));
return Status;
}
.inf文件:
[Defines]
INF_VERSION = 0x00010006
BASE_NAME = XV6Boot
FILE_GUID = 4dc59a5b-97d9-4a08-808f-e979f47508c0
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 0.1
ENTRY_POINT = UefiMain
[Sources]
XV6Boot.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
BmpSupportLib
UefiLib
[Guids]
gEfiFileInfoGuid
[Protocols]
gEfiSimpleFileSystemProtocolGuid
.dsc文件:
[Defines]
PLATFORM_NAME = XV6BootPkg
PLATFORM_GUID = 8365c20a-fc46-4fc8-9300-9499611f3862
PLATFORM_VERSION = 0.1
DSC_SPECIFICATION = 0x00010006
SUPPORTED_ARCHITECTURES = X64
BUILD_TARGETS = DEBUG|RELEASE
[LibraryClasses]
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
[Components]
XV6BootPkg/XV6Boot.inf
二.bin文件实现代码
BITS 64
mov ecx, 0x0013C680
mov eax, 0xFF19679A
xor rdi, rdi
mov rdi, 0x80000000
Write:
mov [rdi], eax
add rdi, 4
loop Write
jmp $
编译命令:
nasm kernel.asm -f bin -o Kernel.bin
三.效果展示
kernel.asm文件的代码会将屏幕填充为蓝色。