From eb076dbf3754f44efdda926e1cc55a5c86136f5c Mon Sep 17 00:00:00 2001 From: Amlal EL Mahrouss Date: Sun, 7 Jul 2024 09:39:07 +0200 Subject: MHR-36: IMP: Add ProgramLoader class, *_cast macros and patching capability. FIX: Device constructor marked as explicit. Signed-off-by: Amlal EL Mahrouss --- Boot/BootKit/BootKit.hxx | 1 + Boot/BootKit/Device.hxx | 2 +- Boot/BootKit/ProgramLoader.hxx | 41 +++++++++++++++++++ Boot/Sources/BootloaderRsrc.rsrc | 4 +- Boot/Sources/HEL/AMD64/BootFileReader.cxx | 55 +++++++++++++++----------- Boot/Sources/HEL/AMD64/BootMain.cxx | 25 ++++++++++++ Boot/Sources/ProgramLoader.cxx | 66 +++++++++++++++++++++++++++++++ Boot/amd64-efi.make | 5 +-- 8 files changed, 169 insertions(+), 30 deletions(-) create mode 100644 Boot/BootKit/ProgramLoader.hxx create mode 100644 Boot/Sources/ProgramLoader.cxx (limited to 'Boot') diff --git a/Boot/BootKit/BootKit.hxx b/Boot/BootKit/BootKit.hxx index c83b3c63..850f3896 100644 --- a/Boot/BootKit/BootKit.hxx +++ b/Boot/BootKit/BootKit.hxx @@ -135,6 +135,7 @@ private: BTextWriter mWriter; EfiFileProtocol* mFile{nullptr}; UInt64 mSizeFile{0}; + EfiFileProtocol* mRootFs; }; typedef UInt8* BlobType; diff --git a/Boot/BootKit/Device.hxx b/Boot/BootKit/Device.hxx index 234ab6bd..2c6ddd6b 100644 --- a/Boot/BootKit/Device.hxx +++ b/Boot/BootKit/Device.hxx @@ -14,7 +14,7 @@ using namespace Kernel; class Device { public: - Device() = default; + explicit Device() = default; virtual ~Device() = default; NEWOS_MOVE_DEFAULT(Device); diff --git a/Boot/BootKit/ProgramLoader.hxx b/Boot/BootKit/ProgramLoader.hxx new file mode 100644 index 00000000..9e14710c --- /dev/null +++ b/Boot/BootKit/ProgramLoader.hxx @@ -0,0 +1,41 @@ +/* ------------------------------------------- + + Copyright Zeta Electronics Corporation + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace Boot +{ + using namespace Kernel; + + class ProgramLoader; + + /// @brief Program loader class + /// @package nl.zeta.boot.api + class ProgramLoader final + { + public: + explicit ProgramLoader() = delete; + ~ProgramLoader() = default; + + explicit ProgramLoader(Kernel::VoidPtr blob); + + ProgramLoader& operator=(const ProgramLoader&) = default; + ProgramLoader(const ProgramLoader&) = default; + + void Start(HEL::HandoverInformationHeader* handover); + const char* GetName(); + void SetName(const char* name); + + private: + Char fBlobName[255]; + VoidPtr fStartAddress{nullptr}; + VoidPtr fBlob{nullptr}; + }; +} // namespace Kernel \ No newline at end of file diff --git a/Boot/Sources/BootloaderRsrc.rsrc b/Boot/Sources/BootloaderRsrc.rsrc index 92ff177f..071cb7ff 100644 --- a/Boot/Sources/BootloaderRsrc.rsrc +++ b/Boot/Sources/BootloaderRsrc.rsrc @@ -1,6 +1,6 @@ #include "../../Kernel/CompilerKit/Version.hxx" -1 ICON "../../Icons/boot-logo.ico" +1 ICON "../../Icons/app-logo.ico" 1 VERSIONINFO FILEVERSION 1,0,0,0 @@ -11,7 +11,7 @@ BEGIN BLOCK "080904E4" BEGIN VALUE "CompanyName", "Zeta Electronics Corporation" - VALUE "FileDescription", "New OS multi-platform bootloader." + VALUE "FileDescription", "New OS Loader." VALUE "FileVersion", BOOTLOADER_VERSION VALUE "InternalName", "newosldr" VALUE "LegalCopyright", "Copyright Zeta Electronics Corporation, all rights reserved." diff --git a/Boot/Sources/HEL/AMD64/BootFileReader.cxx b/Boot/Sources/HEL/AMD64/BootFileReader.cxx index f6984591..d32f2a17 100644 --- a/Boot/Sources/HEL/AMD64/BootFileReader.cxx +++ b/Boot/Sources/HEL/AMD64/BootFileReader.cxx @@ -49,27 +49,26 @@ BFileReader::BFileReader(const CharacterTypeUTF16* path, EfiGUID guidEfp = EfiGUID(EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID); EfiSimpleFilesystemProtocol* efp = nullptr; - EfiFileProtocol* rootFs = nullptr; EfiLoadImageProtocol* img = nullptr; EfiGUID guidImg = EfiGUID(EFI_LOADED_IMAGE_PROTOCOL_GUID); if (BS->HandleProtocol(ImageHandle, &guidImg, (void**)&img) != kEfiOk) { - mWriter.Write(L"newosldr: Fetch-Protocol: No-Such-Protocol").Write(L"\r"); + mWriter.Write(L"newosldr: Handle-Protocol: No-Such-Protocol").Write(L"\r"); this->mErrorCode = kNotSupported; } if (BS->HandleProtocol(img->DeviceHandle, &guidEfp, (void**)&efp) != kEfiOk) { - mWriter.Write(L"newosldr: Fetch-Protocol: No-Such-Protocol").Write(L"\r"); + mWriter.Write(L"newosldr: Handle-Protocol: No-Such-Protocol").Write(L"\r"); this->mErrorCode = kNotSupported; return; } /// Start doing disk I/O - if (efp->OpenVolume(efp, &rootFs) != kEfiOk) + if (efp->OpenVolume(efp, &mRootFs) != kEfiOk) { mWriter.Write(L"newosldr: Fetch-Protocol: No-Such-Volume").Write(L"\r"); this->mErrorCode = kNotSupported; @@ -78,18 +77,19 @@ BFileReader::BFileReader(const CharacterTypeUTF16* path, EfiFileProtocol* kernelFile = nullptr; - if (rootFs->Open(rootFs, &kernelFile, mPath, kEFIFileRead, kEFIReadOnly) != + if (mRootFs->Open(mRootFs, &kernelFile, mPath, kEFIFileRead, kEFIReadOnly) != kEfiOk) { mWriter.Write(L"newosldr: Fetch-Protocol: No-Such-Path: ") .Write(mPath) .Write(L"\r"); this->mErrorCode = kNotSupported; + + mRootFs->Close(mRootFs); + return; } - rootFs->Close(rootFs); - mSizeFile = 0; mFile = kernelFile; mErrorCode = kOperationOkay; @@ -103,22 +103,31 @@ BFileReader::~BFileReader() this->mFile = nullptr; } + if (this->mRootFs) + { + this->mRootFs->Close(this->mRootFs); + this->mRootFs = nullptr; + } + if (this->mBlob) - BS->FreePool(mBlob); + { + BS->FreePool(this->mBlob); + this->mBlob = nullptr; + } BSetMem(this->mPath, 0, kPathLen); } /** @brief Reads all of the file into a buffer. - @param **until** size of file - @param **chunk** chunk to read each time. + @param **readUntil** size of file + @param **chunkToRead** chunk to read each time. */ -Void BFileReader::ReadAll(SizeT until, SizeT chunk) +Void BFileReader::ReadAll(SizeT readUntil, SizeT chunkToRead) { if (mBlob == nullptr) { - if (auto err = BS->AllocatePool(EfiLoaderCode, until, (VoidPtr*)&mBlob) != + if (auto err = BS->AllocatePool(EfiLoaderCode, readUntil, (VoidPtr*)&mBlob) != kEfiOk) { mWriter.Write(L"*** error: ").Write(err).Write(L" ***\r"); @@ -128,26 +137,24 @@ Void BFileReader::ReadAll(SizeT until, SizeT chunk) mErrorCode = kNotSupported; - UInt64 bufSize = chunk; - UInt64 szCnt = 0; - UInt64 curSz = 0; + UInt64 bufSize = chunkToRead; + UInt64 szCnt = 0UL; - while (szCnt < until) + while (szCnt < readUntil) { - if (mFile->Read(mFile, &bufSize, (VoidPtr)((UIntPtr)mBlob + curSz)) != - kEfiOk) - { - break; - } + auto res = mFile->Read(mFile, &bufSize, (VoidPtr)(&((Char*)mBlob)[szCnt])); szCnt += bufSize; - curSz += bufSize; - if (bufSize == 0) + if (res == kBufferTooSmall) + bufSize = chunkToRead; + else if (res == kEfiOk) + bufSize = chunkToRead; + else break; } - mSizeFile = curSz; + mSizeFile = szCnt; mErrorCode = kOperationOkay; } diff --git a/Boot/Sources/HEL/AMD64/BootMain.cxx b/Boot/Sources/HEL/AMD64/BootMain.cxx index e98be361..872aea8e 100644 --- a/Boot/Sources/HEL/AMD64/BootMain.cxx +++ b/Boot/Sources/HEL/AMD64/BootMain.cxx @@ -15,6 +15,7 @@ #include #include #include +#include #include /// make the compiler shut up. @@ -224,13 +225,37 @@ EFI_EXTERN_C EFI_API Int Main(EfiHandlePtr ImageHandle, diskFormatter.Format(kMachineModel, &rootDesc, 1); } +#ifdef __NEWOS_CAN_PATCH__ + + BFileReader readerKernel(L"newoskrnl.exe", ImageHandle); + + readerKernel.ReadAll(kib_cast(5), kib_cast(5)); + + Boot::ProgramLoader* loader = nullptr; + + if (readerKernel.Blob()) + { + loader = new Boot::ProgramLoader(readerKernel.Blob()); + loader->SetName("NewOSKrnl (Patched)"); + } + +#endif // ifdef __NEWOS_CAN_PATCH__ + EFI::ExitBootServices(*MapKey, ImageHandle); // ---------------------------------------------------- // // Fallback to builtin kernel. + // // ---------------------------------------------------- // +#ifdef __NEWOS_CAN_PATCH__ + if (loader) + loader->Start(handoverHdrPtr); + else + hal_init_platform(handoverHdrPtr); +#else hal_init_platform(handoverHdrPtr); +#endif // ifdef __NEWOS_CAN_PATCH__ EFI::Stop(); diff --git a/Boot/Sources/ProgramLoader.cxx b/Boot/Sources/ProgramLoader.cxx new file mode 100644 index 00000000..90175bef --- /dev/null +++ b/Boot/Sources/ProgramLoader.cxx @@ -0,0 +1,66 @@ +/* ------------------------------------------- + + Copyright Zeta Electronics Corporation + +------------------------------------------- */ + +#include +#include +#include +#include + +namespace Boot +{ + ProgramLoader::ProgramLoader(VoidPtr blob) + : fBlob(blob), fStartAddress(nullptr) + { + // detect the format. + const char* firstBytes = reinterpret_cast(fBlob); + + BTextWriter writer; + writer.WriteCharacter(firstBytes[0]).WriteCharacter(firstBytes[1]).WriteCharacter('\r').WriteCharacter('\n'); + + if (!firstBytes) + { + // failed to provide a valid pointer. + return; + } + + if (firstBytes[0] == 'M' && + firstBytes[1] == 'Z') + { + // Parse PE32+ + fStartAddress = nullptr; + } + else if (firstBytes[0] == 'J' && + firstBytes[1] == 'o' && + firstBytes[2] == 'y' && + firstBytes[3] == '!') + { + // Parse Non FAT PEF. + fStartAddress = nullptr; + } + else + { + // probably a binary blob. + fStartAddress = fBlob; + } + } + + Void ProgramLoader::Start(HEL::HandoverInformationHeader* handover) + { + if (!fStartAddress) return; + + ((HEL::HandoverProc)fStartAddress)(handover); + } + + const Char* ProgramLoader::GetName() + { + return fBlobName; + } + + Void ProgramLoader::SetName(const Char* name) + { + CopyMem(fBlobName, name, StrLen(name)); + } +} // namespace Boot \ No newline at end of file diff --git a/Boot/amd64-efi.make b/Boot/amd64-efi.make index 2bbe2a2c..16cb936e 100644 --- a/Boot/amd64-efi.make +++ b/Boot/amd64-efi.make @@ -32,7 +32,7 @@ EMU_FLAGS=-net none -m 4G -M q35 -d int \ -bios $(BIOS) -device piix3-ide,id=ide \ -drive id=disk,file=$(IMG),format=raw,if=none \ -device ide-hd,drive=disk,bus=ide.0 -drive \ - file=fat:rw:Sources/Root,index=2,format=raw -d int -hdd $(IMG_2) + file=fat:rw:Sources/Root/,index=2,format=raw -d int -hdd $(IMG_2) LD_FLAGS=-e Main --subsystem=10 @@ -65,7 +65,6 @@ all: compile-amd64 $(LD_GNU) $(OBJ) $(LD_FLAGS) -o Sources/$(BOOT_LOADER) $(COPY) Sources/$(BOOT_LOADER) Sources/Root/EFI/BOOT/BOOTX64.EFI $(COPY) Sources/$(BOOT_LOADER) Sources/Root/EFI/BOOT/NEWBOOT.EFI - $(COPY) ../Kernel/$(KERNEL) Sources/Root/$(KERNEL) ifneq ($(DEBUG_SUPPORT), ) DEBUG = -D__DEBUG__ @@ -76,7 +75,7 @@ compile-amd64: $(RESCMD) $(CC_GNU) $(NEWOS_MODEL) $(STANDALONE_MACRO) $(FLAG_GNU) $(DEBUG) \ $(wildcard Sources/HEL/AMD64/*.cxx) \ - $(wildcard Sources/HEL/AMD64/*.S) + $(wildcard Sources/HEL/AMD64/*.S) \ $(wildcard Sources/*.cxx) .PHONY: run-efi-amd64 -- cgit v1.2.3