diff options
Diffstat (limited to 'dev/boot')
27 files changed, 2554 insertions, 3021 deletions
diff --git a/dev/boot/BootKit/BitManip.h b/dev/boot/BootKit/BitManip.h index e4af0bf6..b1c72bfb 100644 --- a/dev/boot/BootKit/BitManip.h +++ b/dev/boot/BootKit/BitManip.h @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ @@ -10,11 +10,11 @@ /// File: BitManip.h /// Purpose: Bit manipulation helpers, based on coreboot-dev. -#define bk_set_bit(X, O) X = (1 << O) | X -#define bk_clear_bit(X, O) X = ~(1 << O) & X -#define bk_toogle(X, O) X = (1 << O) ^ X -#define bk_lsb(X) X = X & -X -#define bk_msb(X) X = -(mp_lsb(X)) & X +#define bk_set_bit(X, O) X = (1 << O) | X +#define bk_clear_bit(X, O) X = ~(1 << O) & X +#define bk_toogle(X, O) X = (1 << O) ^ X +#define bk_lsb(X) X = X & -X +#define bk_msb(X) X = -(mp_lsb(X)) & X #define bk_look_for_bit(X, O) (1 << O) | X -#endif // ifndef __BITMANIP_H__ +#endif // ifndef __BITMANIP_H__ diff --git a/dev/boot/BootKit/BootKit.h b/dev/boot/BootKit/BootKit.h index 7b2a4f0a..76821b20 100644 --- a/dev/boot/BootKit/BootKit.h +++ b/dev/boot/BootKit/BootKit.h @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ @@ -17,8 +17,8 @@ /// include NeFS header and Support header as well. -#include <FSKit/NeFS.h> #include <BootKit/Support.h> +#include <FSKit/NeFS.h> /***********************************************************************************/ /// Include other APIs. @@ -27,389 +27,370 @@ #include <NewKit/Defines.h> #include <modules/ATA/ATA.h> -#include <FirmwareKit/VEPM.h> +#include <FirmwareKit/EFI.h> #include <FirmwareKit/EPM.h> #include <FirmwareKit/GPT.h> -#include <FirmwareKit/EFI.h> +#include <FirmwareKit/VEPM.h> #define kBKBootFileMime "boot-x/file" -#define kBKBootDirMime "boot-x/dir" +#define kBKBootDirMime "boot-x/dir" /***********************************************************************************/ /// Framebuffer helpers. /***********************************************************************************/ -namespace Boot -{ - EXTERN void ThrowError(const WideChar* errorCode, - const WideChar* reason) noexcept; - - class BootTextWriter; - class BootFileReader; - class BootThread; - class BVersionString; - - typedef Char* PEFImagePtr; - typedef Char* PEImagePtr; - - typedef WideChar CharacterTypeUTF16; - typedef Char CharacterTypeUTF8; - - using namespace Kernel; - - /** - * @brief BootKit Text Writer class - * Writes to UEFI StdOut. - */ - class BootTextWriter final - { - BootTextWriter& _Write(const UInt64& num); - - public: - BootTextWriter& Write(const UInt64& num); - BootTextWriter& Write(const Char* str); - BootTextWriter& Write(const CharacterTypeUTF16* str); - BootTextWriter& WriteCharacter(CharacterTypeUTF16 c); - BootTextWriter& Write(const UChar* str); - - template <typename T> - BootTextWriter& operator<<(T elem) - { - this->Write(elem); - return *this; - } - - public: - explicit BootTextWriter() = default; - ~BootTextWriter() = default; - - public: - BootTextWriter& operator=(const BootTextWriter&) = default; - BootTextWriter(const BootTextWriter&) = default; - }; - - Kernel::SizeT BCopyMem(CharacterTypeUTF16* dest, CharacterTypeUTF16* src, const Kernel::SizeT len); - - Kernel::SizeT BSetMem(CharacterTypeUTF8* src, const CharacterTypeUTF8 byte, const Kernel::SizeT len); - - /// String length functions. - - /// @brief get string length. - Kernel::SizeT BStrLen(const CharacterTypeUTF16* ptr); - - /// @brief set memory with custom value. - Kernel::SizeT BSetMem(CharacterTypeUTF16* src, const CharacterTypeUTF16 byte, const Kernel::SizeT len); - - /** - * @brief BootKit File Reader class - * Reads the Firmware Boot partition and filesystem. - */ - class BootFileReader final - { - public: - explicit BootFileReader(const CharacterTypeUTF16* path, - EfiHandlePtr ImageHandle); - ~BootFileReader(); - - public: - Void ReadAll(SizeT until, SizeT chunk = kib_cast(4), UIntPtr out_address = 0UL); - - enum - { - kOperationOkay, - kNotSupported, - kEmptyDirectory, - kNoSuchEntry, - kIsDirectory, - kTooSmall, - kCount, - }; - - /// @brief error code getter. - /// @return the error code. - Int32& Error(); - - /// @brief blob getter. - /// @return the blob. - VoidPtr Blob(); - - /// @breif Size getter. - /// @return the size of the file. - UInt64& Size(); - - public: - BootFileReader& operator=(const BootFileReader&) = default; - BootFileReader(const BootFileReader&) = default; - - private: - Int32 mErrorCode{kOperationOkay}; - VoidPtr mBlob{nullptr}; - CharacterTypeUTF16 mPath[kPathLen]; - BootTextWriter mWriter; - EfiFileProtocol* mFile{nullptr}; - UInt64 mSizeFile{0}; - EfiFileProtocol* mRootFs; - }; - - typedef UInt8* BlobType; - - class BVersionString final - { - public: - static const CharacterTypeUTF8* The() - { - return BOOTLOADER_VERSION; - } - }; - - /***********************************************************************************/ - /// Provide some useful processor features. - /***********************************************************************************/ +namespace Boot { +EXTERN void ThrowError(const WideChar* errorCode, const WideChar* reason) noexcept; + +class BootTextWriter; +class BootFileReader; +class BootThread; +class BVersionString; + +typedef Char* PEFImagePtr; +typedef Char* PEImagePtr; + +typedef WideChar CharacterTypeUTF16; +typedef Char CharacterTypeUTF8; + +using namespace Kernel; + +/** + * @brief BootKit Text Writer class + * Writes to UEFI StdOut. + */ +class BootTextWriter final { + BootTextWriter& _Write(const UInt64& num); + + public: + BootTextWriter& Write(const UInt64& num); + BootTextWriter& Write(const Char* str); + BootTextWriter& Write(const CharacterTypeUTF16* str); + BootTextWriter& WriteCharacter(CharacterTypeUTF16 c); + BootTextWriter& Write(const UChar* str); + + template <typename T> + BootTextWriter& operator<<(T elem) { + this->Write(elem); + return *this; + } + + public: + explicit BootTextWriter() = default; + ~BootTextWriter() = default; + + public: + BootTextWriter& operator=(const BootTextWriter&) = default; + BootTextWriter(const BootTextWriter&) = default; +}; + +Kernel::SizeT BCopyMem(CharacterTypeUTF16* dest, CharacterTypeUTF16* src, const Kernel::SizeT len); + +Kernel::SizeT BSetMem(CharacterTypeUTF8* src, const CharacterTypeUTF8 byte, + const Kernel::SizeT len); + +/// String length functions. + +/// @brief get string length. +Kernel::SizeT BStrLen(const CharacterTypeUTF16* ptr); + +/// @brief set memory with custom value. +Kernel::SizeT BSetMem(CharacterTypeUTF16* src, const CharacterTypeUTF16 byte, + const Kernel::SizeT len); + +/** + * @brief BootKit File Reader class + * Reads the Firmware Boot partition and filesystem. + */ +class BootFileReader final { + public: + explicit BootFileReader(const CharacterTypeUTF16* path, EfiHandlePtr ImageHandle); + ~BootFileReader(); + + public: + Void ReadAll(SizeT until, SizeT chunk = kib_cast(4), UIntPtr out_address = 0UL); + + enum { + kOperationOkay, + kNotSupported, + kEmptyDirectory, + kNoSuchEntry, + kIsDirectory, + kTooSmall, + kCount, + }; + + /// @brief error code getter. + /// @return the error code. + Int32& Error(); + + /// @brief blob getter. + /// @return the blob. + VoidPtr Blob(); + + /// @breif Size getter. + /// @return the size of the file. + UInt64& Size(); + + public: + BootFileReader& operator=(const BootFileReader&) = default; + BootFileReader(const BootFileReader&) = default; + + private: + Int32 mErrorCode{kOperationOkay}; + VoidPtr mBlob{nullptr}; + CharacterTypeUTF16 mPath[kPathLen]; + BootTextWriter mWriter; + EfiFileProtocol* mFile{nullptr}; + UInt64 mSizeFile{0}; + EfiFileProtocol* mRootFs; +}; + +typedef UInt8* BlobType; + +class BVersionString final { + public: + static const CharacterTypeUTF8* The() { return BOOTLOADER_VERSION; } +}; + +/***********************************************************************************/ +/// Provide some useful processor features. +/***********************************************************************************/ #ifdef __EFI_x86_64__ - /*** - * Common processor instructions. - */ - - EXTERN_C void rt_out8(UInt16 port, UInt8 value); - EXTERN_C void rt_out16(UInt16 port, UInt16 value); - EXTERN_C void rt_out32(UInt16 port, UInt32 value); - EXTERN_C UInt8 rt_in8(UInt16 port); - EXTERN_C UInt16 In16(UInt16 port); - EXTERN_C UInt32 rt_in32(UInt16 port); - - EXTERN_C void rt_hlt(); - EXTERN_C void rt_cli(); - EXTERN_C void rt_sti(); - EXTERN_C void rt_cld(); - EXTERN_C void rt_std(); - -#endif // __EFI_x86_64__ - - /// @brief BootKit Drive Formatter. - template <typename BootDev> - class BDiskFormatFactory final - { - public: - /// @brief File entry for **BDiskFormatFactory**. - struct BFileDescriptor final - { - Char fFileName[kNeFSCatalogNameLen]; - Int32 fKind; - }; - - public: - explicit BDiskFormatFactory() = default; - ~BDiskFormatFactory() = default; - - NE_COPY_DELETE(BDiskFormatFactory) - - /// @brief Format disk using partition name and blob. - /// @param Partition part_name the target partition name. - /// @param blob blobs array. - /// @param blob_sz blobs array count. - /// @retval True disk has been formatted. - /// @retval False failed to format. - Boolean Format(const Char* part_name); - - /// @brief check if partition is good. - Bool IsPartitionValid() noexcept - { +/*** + * Common processor instructions. + */ + +EXTERN_C void rt_out8(UInt16 port, UInt8 value); +EXTERN_C void rt_out16(UInt16 port, UInt16 value); +EXTERN_C void rt_out32(UInt16 port, UInt32 value); +EXTERN_C UInt8 rt_in8(UInt16 port); +EXTERN_C UInt16 In16(UInt16 port); +EXTERN_C UInt32 rt_in32(UInt16 port); + +EXTERN_C void rt_hlt(); +EXTERN_C void rt_cli(); +EXTERN_C void rt_sti(); +EXTERN_C void rt_cld(); +EXTERN_C void rt_std(); + +#endif // __EFI_x86_64__ + +/// @brief BootKit Drive Formatter. +template <typename BootDev> +class BDiskFormatFactory final { + public: + /// @brief File entry for **BDiskFormatFactory**. + struct BFileDescriptor final { + Char fFileName[kNeFSCatalogNameLen]; + Int32 fKind; + }; + + public: + explicit BDiskFormatFactory() = default; + ~BDiskFormatFactory() = default; + + NE_COPY_DELETE(BDiskFormatFactory) + + /// @brief Format disk using partition name and blob. + /// @param Partition part_name the target partition name. + /// @param blob blobs array. + /// @param blob_sz blobs array count. + /// @retval True disk has been formatted. + /// @retval False failed to format. + Boolean Format(const Char* part_name); + + /// @brief check if partition is good. + Bool IsPartitionValid() noexcept { #if defined(BOOTZ_EPM_SUPPORT) - fDiskDev.Leak().mBase = (kEPMBootBlockLba); - fDiskDev.Leak().mSize = sizeof(EPM_PART_BLOCK); + fDiskDev.Leak().mBase = (kEPMBootBlockLba); + fDiskDev.Leak().mSize = sizeof(EPM_PART_BLOCK); - EPM_PART_BLOCK buf_epm = {}; + EPM_PART_BLOCK buf_epm = {}; - fDiskDev.Read((Char*)&buf_epm, sizeof(EPM_PART_BLOCK)); + fDiskDev.Read((Char*) &buf_epm, sizeof(EPM_PART_BLOCK)); - if (StrCmp(buf_epm.Magic, kEPMMagic)) - { - return false; - } + if (StrCmp(buf_epm.Magic, kEPMMagic)) { + return false; + } - if (buf_epm.Version != kEPMRevisionBcd) - { - return false; - } + if (buf_epm.Version != kEPMRevisionBcd) { + return false; + } - fDiskDev.Leak().mBase = (kNeFSRootCatalogStartAddress); - fDiskDev.Leak().mSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); + fDiskDev.Leak().mBase = (kNeFSRootCatalogStartAddress); + fDiskDev.Leak().mSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - Char buf[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0}; + Char buf[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0}; - fDiskDev.Read(buf, sizeof(NEFS_ROOT_PARTITION_BLOCK)); + fDiskDev.Read(buf, sizeof(NEFS_ROOT_PARTITION_BLOCK)); - NEFS_ROOT_PARTITION_BLOCK* blockPart = reinterpret_cast<NEFS_ROOT_PARTITION_BLOCK*>(buf); + NEFS_ROOT_PARTITION_BLOCK* blockPart = reinterpret_cast<NEFS_ROOT_PARTITION_BLOCK*>(buf); - BootTextWriter writer; + BootTextWriter writer; - for (SizeT indexMag = 0UL; indexMag < kNeFSIdentLen; ++indexMag) - { - if (blockPart->Ident[indexMag] != kNeFSIdent[indexMag]) - return false; - } + for (SizeT indexMag = 0UL; indexMag < kNeFSIdentLen; ++indexMag) { + if (blockPart->Ident[indexMag] != kNeFSIdent[indexMag]) return false; + } - if (blockPart->DiskSize != this->fDiskDev.GetDiskSize() || - blockPart->DiskSize < 1 || - blockPart->SectorSize != BootDev::kSectorSize || - blockPart->Version != kNeFSVersionInteger || - blockPart->StartCatalog == 0) - { - return false; - } - else if (blockPart->PartitionName[0] == 0) - { - return false; - } + if (blockPart->DiskSize != this->fDiskDev.GetDiskSize() || blockPart->DiskSize < 1 || + blockPart->SectorSize != BootDev::kSectorSize || + blockPart->Version != kNeFSVersionInteger || blockPart->StartCatalog == 0) { + return false; + } else if (blockPart->PartitionName[0] == 0) { + return false; + } - writer.Write(L"BootZ: NeFS Partition: ").Write(blockPart->PartitionName).Write(L" is healthy.\r"); + writer.Write(L"BootZ: NeFS Partition: ") + .Write(blockPart->PartitionName) + .Write(L" is healthy.\r"); - return true; + return true; #else - GPT_PARTITION_TABLE gpt_part{}; + GPT_PARTITION_TABLE gpt_part{}; - fDiskDev.Leak().mBase = (kGPTPartitionTableLBA); - fDiskDev.Leak().mSize = sizeof(GPT_PARTITION_TABLE); + fDiskDev.Leak().mBase = (kGPTPartitionTableLBA); + fDiskDev.Leak().mSize = sizeof(GPT_PARTITION_TABLE); - fDiskDev.Read((Char*)&gpt_part, sizeof(GPT_PARTITION_TABLE)); + fDiskDev.Read((Char*) &gpt_part, sizeof(GPT_PARTITION_TABLE)); - BootTextWriter writer; + BootTextWriter writer; - if (StrCmp(gpt_part.Signature, kMagicGPT) == 0) - { - writer.Write("BootZ: GPT Partition found.\r"); - return true; - } + if (StrCmp(gpt_part.Signature, kMagicGPT) == 0) { + writer.Write("BootZ: GPT Partition found.\r"); + return true; + } - writer.Write("BootZ: No Partition found.\r"); + writer.Write("BootZ: No Partition found.\r"); - return false; + return false; #endif - } - - private: - BootDev fDiskDev; - }; - - /// @brief Format disk with a specific partition scheme. - /// @param part_name partition Name - /// @param blob blos. - /// @param blob_sz n blobs (n * sizeof(blob_struct)). - /// @retval True disk has been formatted. - /// @retval False failed to format. - template <typename BootDev> - inline Boolean BDiskFormatFactory<BootDev>::Format(const Char* part_name) - { + } + + private: + BootDev fDiskDev; +}; + +/// @brief Format disk with a specific partition scheme. +/// @param part_name partition Name +/// @param blob blos. +/// @param blob_sz n blobs (n * sizeof(blob_struct)). +/// @retval True disk has been formatted. +/// @retval False failed to format. +template <typename BootDev> +inline Boolean BDiskFormatFactory<BootDev>::Format(const Char* part_name) { #if defined(BOOTZ_EPM_SUPPORT) - /// @note A catalog roughly equal to a sector in NeFS terms. - constexpr auto kMinimumDiskSize = kNeFSMinimumDiskSize; // at minimum. + /// @note A catalog roughly equal to a sector in NeFS terms. + constexpr auto kMinimumDiskSize = kNeFSMinimumDiskSize; // at minimum. - /// @note also look at EPM headers, for free part blocks. (only applies if EPM or vEPM is used) + /// @note also look at EPM headers, for free part blocks. (only applies if EPM or vEPM is used) - if (fDiskDev.GetDiskSize() < kMinimumDiskSize) - { - Boot::ThrowError(L"Drive-Too-Tiny", L"Can't format a NeFS partition here."); - return false; - } + if (fDiskDev.GetDiskSize() < kMinimumDiskSize) { + Boot::ThrowError(L"Drive-Too-Tiny", L"Can't format a NeFS partition here."); + return false; + } - NEFS_ROOT_PARTITION_BLOCK part{}; + NEFS_ROOT_PARTITION_BLOCK part{}; - CopyMem(part.Ident, kNeFSIdent, kNeFSIdentLen - 1); - CopyMem(part.PartitionName, part_name, StrLen(part_name)); + CopyMem(part.Ident, kNeFSIdent, kNeFSIdentLen - 1); + CopyMem(part.PartitionName, part_name, StrLen(part_name)); - part.Version = kNeFSVersionInteger; - part.CatalogCount = blob_sz; - part.Kind = BootDev::kSectorSize; - part.SectorSize = kATASectorSize; - part.FreeCatalog = fDiskDev.GetSectorsCount() / sizeof(NEFS_CATALOG_STRUCT); - part.SectorCount = fDiskDev.GetSectorsCount(); - part.FreeSectors = fDiskDev.GetSectorsCount(); - part.StartCatalog = kNeFSCatalogStartAddress; - part.DiskSize = fDiskDev.GetDiskSize(); - part.Flags = kNeFSPartitionTypeBoot | kNeFSPartitionTypeStandard; + part.Version = kNeFSVersionInteger; + part.CatalogCount = blob_sz; + part.Kind = BootDev::kSectorSize; + part.SectorSize = kATASectorSize; + part.FreeCatalog = fDiskDev.GetSectorsCount() / sizeof(NEFS_CATALOG_STRUCT); + part.SectorCount = fDiskDev.GetSectorsCount(); + part.FreeSectors = fDiskDev.GetSectorsCount(); + part.StartCatalog = kNeFSCatalogStartAddress; + part.DiskSize = fDiskDev.GetDiskSize(); + part.Flags = kNeFSPartitionTypeBoot | kNeFSPartitionTypeStandard; - BootTextWriter writer; + BootTextWriter writer; - writer << "BootZ: Partition name: " << part.PartitionName << "\r"; - writer << "BootZ: Start: " << part.StartCatalog << "\r"; - writer << "BootZ: Number of catalogs: " << part.CatalogCount << "\r"; - writer << "BootZ: Free catalog: " << part.FreeCatalog << "\r"; - writer << "BootZ: Free sectors: " << part.FreeSectors << "\r"; - writer << "BootZ: Sector size: " << part.SectorSize << "\r"; + writer << "BootZ: Partition name: " << part.PartitionName << "\r"; + writer << "BootZ: Start: " << part.StartCatalog << "\r"; + writer << "BootZ: Number of catalogs: " << part.CatalogCount << "\r"; + writer << "BootZ: Free catalog: " << part.FreeCatalog << "\r"; + writer << "BootZ: Free sectors: " << part.FreeSectors << "\r"; + writer << "BootZ: Sector size: " << part.SectorSize << "\r"; - EPM_PART_BLOCK epm_boot{}; + EPM_PART_BLOCK epm_boot{}; - const auto kFsName = "NeFS"; - const auto kBlockName = "OS (EPM)"; + const auto kFsName = "NeFS"; + const auto kBlockName = "OS (EPM)"; - epm_boot.FsVersion = kNeFSVersionInteger; - epm_boot.LbaStart = kNeFSRootCatalogStartAddress; - epm_boot.LbaEnd = fDiskDev.GetDiskSize(); - epm_boot.SectorSz = part.SectorSize; - epm_boot.Kind = kEPMNeKernel; - epm_boot.NumBlocks = part.CatalogCount; + epm_boot.FsVersion = kNeFSVersionInteger; + epm_boot.LbaStart = kNeFSRootCatalogStartAddress; + epm_boot.LbaEnd = fDiskDev.GetDiskSize(); + epm_boot.SectorSz = part.SectorSize; + epm_boot.Kind = kEPMNeKernel; + epm_boot.NumBlocks = part.CatalogCount; - epm_boot.Guid = kEPMNilGuid; + epm_boot.Guid = kEPMNilGuid; - CopyMem(epm_boot.Fs, reinterpret_cast<VoidPtr>(const_cast<Char*>(kFsName)), StrLen(kFsName)); - CopyMem(epm_boot.Name, reinterpret_cast<VoidPtr>(const_cast<Char*>(kBlockName)), StrLen(kBlockName)); - CopyMem(epm_boot.Magic, reinterpret_cast<VoidPtr>(const_cast<Char*>(kEPMMagic)), StrLen(kEPMMagic)); + CopyMem(epm_boot.Fs, reinterpret_cast<VoidPtr>(const_cast<Char*>(kFsName)), StrLen(kFsName)); + CopyMem(epm_boot.Name, reinterpret_cast<VoidPtr>(const_cast<Char*>(kBlockName)), + StrLen(kBlockName)); + CopyMem(epm_boot.Magic, reinterpret_cast<VoidPtr>(const_cast<Char*>(kEPMMagic)), + StrLen(kEPMMagic)); - fDiskDev.Leak().mBase = kEPMBootBlockLba; // always always resies at zero block. - fDiskDev.Leak().mSize = sizeof(EPM_PART_BLOCK); + fDiskDev.Leak().mBase = kEPMBootBlockLba; // always always resies at zero block. + fDiskDev.Leak().mSize = sizeof(EPM_PART_BLOCK); - fDiskDev.Write((Char*)&epm_boot, sizeof(EPM_PART_BLOCK)); + fDiskDev.Write((Char*) &epm_boot, sizeof(EPM_PART_BLOCK)); - fDiskDev.Leak().mBase = kNeFSRootCatalogStartAddress; - fDiskDev.Leak().mSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); + fDiskDev.Leak().mBase = kNeFSRootCatalogStartAddress; + fDiskDev.Leak().mSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - fDiskDev.Write((Char*)&part, sizeof(NEFS_ROOT_PARTITION_BLOCK)); + fDiskDev.Write((Char*) &part, sizeof(NEFS_ROOT_PARTITION_BLOCK)); - writer.Write(L"BootZ: Drive is EPM formatted.\r"); + writer.Write(L"BootZ: Drive is EPM formatted.\r"); #elif defined(BOOTZ_VEPM_SUPPORT) - NE_UNUSED(part_name); + NE_UNUSED(part_name); - GPT_PARTITION_TABLE gpt_part{}; + GPT_PARTITION_TABLE gpt_part{}; - CopyMem(gpt_part.Signature, reinterpret_cast<VoidPtr>(const_cast<Char*>(kMagicGPT)), StrLen(kMagicGPT)); + CopyMem(gpt_part.Signature, reinterpret_cast<VoidPtr>(const_cast<Char*>(kMagicGPT)), + StrLen(kMagicGPT)); - gpt_part.Revision = 0x00010000; - gpt_part.HeaderSize = sizeof(GPT_PARTITION_TABLE); + gpt_part.Revision = 0x00010000; + gpt_part.HeaderSize = sizeof(GPT_PARTITION_TABLE); - gpt_part.CRC32 = 0x00000000; + gpt_part.CRC32 = 0x00000000; - gpt_part.Reserved1 = 0x00000000; - gpt_part.LBAHeader = 0x00000000; - gpt_part.LBAAltHeader = 0x00000000; - gpt_part.FirstGPTEntry = 0x00000000; - gpt_part.LastGPTEntry = 0x00000000; + gpt_part.Reserved1 = 0x00000000; + gpt_part.LBAHeader = 0x00000000; + gpt_part.LBAAltHeader = 0x00000000; + gpt_part.FirstGPTEntry = 0x00000000; + gpt_part.LastGPTEntry = 0x00000000; - gpt_part.Guid.Data1 = 0x00000000; - gpt_part.Guid.Data2 = 0x0000; - gpt_part.Guid.Data3 = 0x0000; + gpt_part.Guid.Data1 = 0x00000000; + gpt_part.Guid.Data2 = 0x0000; + gpt_part.Guid.Data3 = 0x0000; - SetMem(gpt_part.Guid.Data4, 0, 8); + SetMem(gpt_part.Guid.Data4, 0, 8); - gpt_part.Revision = 0x00010000; + gpt_part.Revision = 0x00010000; - gpt_part.StartingLBA = 0x00000000; - gpt_part.NumPartitionEntries = 0x00000000; - gpt_part.SizeOfEntries = 0x00000000; - gpt_part.CRC32PartEntry = 0x00000000; + gpt_part.StartingLBA = 0x00000000; + gpt_part.NumPartitionEntries = 0x00000000; + gpt_part.SizeOfEntries = 0x00000000; + gpt_part.CRC32PartEntry = 0x00000000; - SetMem(gpt_part.Reserved2, 0, kSectorAlignGPT_PartTbl); + SetMem(gpt_part.Reserved2, 0, kSectorAlignGPT_PartTbl); - fDiskDev.Leak().mBase = kGPTPartitionTableLBA; // always always resies at zero block. - fDiskDev.Leak().mSize = sizeof(GPT_PARTITION_TABLE); + fDiskDev.Leak().mBase = kGPTPartitionTableLBA; // always always resies at zero block. + fDiskDev.Leak().mSize = sizeof(GPT_PARTITION_TABLE); - fDiskDev.Write((Char*)&gpt_part, sizeof(GPT_PARTITION_TABLE)); + fDiskDev.Write((Char*) &gpt_part, sizeof(GPT_PARTITION_TABLE)); - BootTextWriter writer; - writer.Write(L"BootZ: Drive is GPT formatted.\r"); + BootTextWriter writer; + writer.Write(L"BootZ: Drive is GPT formatted.\r"); #endif - return YES; - } -} // namespace Boot + return YES; +} +} // namespace Boot diff --git a/dev/boot/BootKit/BootThread.h b/dev/boot/BootKit/BootThread.h index 21202f91..b1b801d5 100644 --- a/dev/boot/BootKit/BootThread.h +++ b/dev/boot/BootKit/BootThread.h @@ -1,43 +1,41 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ #pragma once -#include <KernelKit/PE.h> -#include <KernelKit/MSDOS.h> #include <FirmwareKit/Handover.h> +#include <KernelKit/MSDOS.h> +#include <KernelKit/PE.h> + +namespace Boot { +using namespace Kernel; + +class BootThread; + +/// @brief Bootloader Thread class. +class BootThread final { + public: + explicit BootThread() = delete; + ~BootThread() = default; + + explicit BootThread(Kernel::VoidPtr blob); + + BootThread& operator=(const BootThread&) = default; + BootThread(const BootThread&) = default; + + Int32 Start(HEL::BootInfoHeader* handover, BOOL is_own_stack); + void SetName(const char* name); + const char* GetName(); + bool IsValid(); -namespace Boot -{ - using namespace Kernel; - - class BootThread; - - /// @brief Bootloader Thread class. - class BootThread final - { - public: - explicit BootThread() = delete; - ~BootThread() = default; - - explicit BootThread(Kernel::VoidPtr blob); - - BootThread& operator=(const BootThread&) = default; - BootThread(const BootThread&) = default; - - Int32 Start(HEL::BootInfoHeader* handover, BOOL is_own_stack); - void SetName(const char* name); - const char* GetName(); - bool IsValid(); - - private: - Char fBlobName[256U] = {"BootThread"}; - VoidPtr fStartAddress{nullptr}; - VoidPtr fBlob{nullptr}; - UInt8* fStack{nullptr}; - HEL::BootInfoHeader* fHandover{nullptr}; - }; -} // namespace Boot + private: + Char fBlobName[256U] = {"BootThread"}; + VoidPtr fStartAddress{nullptr}; + VoidPtr fBlob{nullptr}; + UInt8* fStack{nullptr}; + HEL::BootInfoHeader* fHandover{nullptr}; +}; +} // namespace Boot diff --git a/dev/boot/BootKit/Device.h b/dev/boot/BootKit/Device.h index 88574bd6..8f5bf854 100644 --- a/dev/boot/BootKit/Device.h +++ b/dev/boot/BootKit/Device.h @@ -1,35 +1,33 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ #pragma once -#include <modules/ATA/ATA.h> #include <modules/AHCI/AHCI.h> +#include <modules/ATA/ATA.h> using namespace Kernel; /// @brief Device type. -class Device -{ -public: - explicit Device() = default; - virtual ~Device() = default; +class Device { + public: + explicit Device() = default; + virtual ~Device() = default; - NE_MOVE_DEFAULT(Device) + NE_MOVE_DEFAULT(Device) - struct Trait - { - SizeT mBase{1024}; - SizeT mSize{1024}; - }; + struct Trait { + SizeT mBase{1024}; + SizeT mSize{1024}; + }; - virtual Trait& Leak() = 0; + virtual Trait& Leak() = 0; - virtual Device& Read(Char* Buf, SizeT SecCount) = 0; - virtual Device& Write(Char* Buf, SizeT SecCount) = 0; + virtual Device& Read(Char* Buf, SizeT SecCount) = 0; + virtual Device& Write(Char* Buf, SizeT SecCount) = 0; }; typedef Device BootDevice; diff --git a/dev/boot/BootKit/EPM.h b/dev/boot/BootKit/EPM.h index 03305c86..907f36e3 100644 --- a/dev/boot/BootKit/EPM.h +++ b/dev/boot/BootKit/EPM.h @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ diff --git a/dev/boot/BootKit/HW/ATA.h b/dev/boot/BootKit/HW/ATA.h index 56393125..adb5c899 100644 --- a/dev/boot/BootKit/HW/ATA.h +++ b/dev/boot/BootKit/HW/ATA.h @@ -1,56 +1,47 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ #pragma once -#include <modules/ATA/ATA.h> #include <BootKit/Device.h> +#include <modules/ATA/ATA.h> using namespace Kernel; -class BootDeviceATA final : public Device -{ -public: - enum - { - kPrimary = ATA_PRIMARY_IO, - kSecondary = ATA_SECONDARY_IO, - }; +class BootDeviceATA final : public Device { + public: + enum { + kPrimary = ATA_PRIMARY_IO, + kSecondary = ATA_SECONDARY_IO, + }; - explicit BootDeviceATA() noexcept; - ~BootDeviceATA() = default; + explicit BootDeviceATA() noexcept; + ~BootDeviceATA() = default; - enum - { - kSectorSize = kATASectorSize - }; + enum { kSectorSize = kATASectorSize }; - struct ATATrait final : public Device::Trait - { - UInt16 mBus{kPrimary}; - UInt8 mMaster{0}; - Boolean mErr{false}; + struct ATATrait final : public Device::Trait { + UInt16 mBus{kPrimary}; + UInt8 mMaster{0}; + Boolean mErr{false}; - operator bool() - { - return !mErr; - } - }; + operator bool() { return !mErr; } + }; -public: - operator bool(); + public: + operator bool(); - SizeT GetSectorsCount() noexcept; - SizeT GetDiskSize() noexcept; + SizeT GetSectorsCount() noexcept; + SizeT GetDiskSize() noexcept; - BootDeviceATA& Read(Char* Buf, SizeT SecCount) override; - BootDeviceATA& Write(Char* Buf, SizeT SecCount) override; + BootDeviceATA& Read(Char* Buf, SizeT SecCount) override; + BootDeviceATA& Write(Char* Buf, SizeT SecCount) override; - ATATrait& Leak() override; + ATATrait& Leak() override; -private: - ATATrait mTrait; + private: + ATATrait mTrait; }; diff --git a/dev/boot/BootKit/HW/SATA.h b/dev/boot/BootKit/HW/SATA.h index 4073d959..7e84c061 100644 --- a/dev/boot/BootKit/HW/SATA.h +++ b/dev/boot/BootKit/HW/SATA.h @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ @@ -9,38 +9,30 @@ #include <CompilerKit/CompilerKit.h> #include <modules/AHCI/AHCI.h> -class BootDeviceSATA final -{ -public: - explicit BootDeviceSATA() noexcept; - ~BootDeviceSATA() = default; +class BootDeviceSATA final { + public: + explicit BootDeviceSATA() noexcept; + ~BootDeviceSATA() = default; - NE_COPY_DEFAULT(BootDeviceSATA) + NE_COPY_DEFAULT(BootDeviceSATA) - struct SATATrait final - { - Kernel::SizeT mBase{1024}; - Kernel::Boolean mErr{false}; - Kernel::Boolean mDetected{false}; + struct SATATrait final { + Kernel::SizeT mBase{1024}; + Kernel::Boolean mErr{false}; + Kernel::Boolean mDetected{false}; - operator bool() - { - return !this->mErr; - } - }; + operator bool() { return !this->mErr; } + }; - operator bool() - { - return this->Leak().mDetected; - } + operator bool() { return this->Leak().mDetected; } - BootDeviceSATA& Read(Kernel::WideChar* Buf, const Kernel::SizeT SecCount); - BootDeviceSATA& Write(Kernel::WideChar* Buf, const Kernel::SizeT SecCount); + BootDeviceSATA& Read(Kernel::WideChar* Buf, const Kernel::SizeT SecCount); + BootDeviceSATA& Write(Kernel::WideChar* Buf, const Kernel::SizeT SecCount); - SATATrait& Leak(); + SATATrait& Leak(); -private: - SATATrait mTrait; + private: + SATATrait mTrait; }; #define kAHCISectorSz 4096 diff --git a/dev/boot/BootKit/Platform.h b/dev/boot/BootKit/Platform.h index e3eac52c..fdef85cb 100644 --- a/dev/boot/BootKit/Platform.h +++ b/dev/boot/BootKit/Platform.h @@ -1,14 +1,14 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ #pragma once /** - @file Platform.h - @brief Platform specific code. + @file Platform.h + @brief Platform specific code. */ #ifdef __x86_64__ @@ -21,7 +21,7 @@ #ifndef EXTERN_C #define EXTERN_C extern #endif -#endif // __cplusplus +#endif // __cplusplus EXTERN_C void rt_halt(); EXTERN_C void rt_cli(); diff --git a/dev/boot/BootKit/Protocol.h b/dev/boot/BootKit/Protocol.h index d5bd62b5..4341a347 100644 --- a/dev/boot/BootKit/Protocol.h +++ b/dev/boot/BootKit/Protocol.h @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ diff --git a/dev/boot/BootKit/Qr.h b/dev/boot/BootKit/Qr.h index 1bf9fa3d..2dcfc5fe 100644 --- a/dev/boot/BootKit/Qr.h +++ b/dev/boot/BootKit/Qr.h @@ -5,969 +5,793 @@ #include <BootKit/Shared/bit.h> #include <BootKit/QrPrelude.h> -#include <modules/CoreGfx/CoreGfx.h> #include <BootKit/Support.h> #include <CompilerKit/Detail.h> +#include <modules/CoreGfx/CoreGfx.h> + +/// @note the QR code is still code 128, it utilizes the same concept of having it's own character +/// set. + +namespace qr { +inline uint8_t min_poly = 0b11101, /* Minimal polynomial x^8 + x^4 + x^3 + x^2 + 1 */ + generator = 0b10; /* Generator of Galois field */ + +/// @brief galois finite field multiplication. +inline uint8_t gf_mul(uint8_t a, uint8_t b) { + uint8_t res = 0; + + for (; b; b >>= 1) { + if (b & 1) res ^= a; + if (a & 0x80) + a = (a << 1) ^ min_poly; + else + a <<= 1; + } + + return res; +} + +// Size of Ecc block with respect to level and version. 0 version is for +// padding. +constexpr int ECC_CODEWORDS_PER_BLOCK[4][41] = { + {0, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, + 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, + {0, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, + 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, + {0, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, + 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, + {0, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, + 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, +}; + +// Number of Ecc blocks with respect to level and version. 0 version is for +// padding. +constexpr int N_ECC_BLOCKS[4][41] = { + {0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, + 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, + {0, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, + 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, + {0, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, + 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, + {0, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, + 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, +}; + +// Positions of central modules of alignment patterns according to version. 0 +// version is for padding. +constexpr int ALIGN_POS[41][7] = { + {}, + {0}, + {6, 18}, + {6, 22}, + {6, 26}, + {6, 30}, + {6, 34}, + {6, 22, 38}, + {6, 24, 42}, + {6, 26, 46}, + {6, 28, 50}, + {6, 30, 54}, + {6, 32, 58}, + {6, 34, 62}, + {6, 26, 46, 66}, + {6, 26, 48, 70}, + {6, 26, 50, 74}, + {6, 30, 54, 78}, + {6, 30, 56, 82}, + {6, 30, 58, 86}, + {6, 34, 62, 90}, + {6, 28, 50, 72, 94}, + {6, 26, 50, 74, 98}, + {6, 30, 54, 78, 102}, + {6, 28, 54, 80, 106}, + {6, 32, 58, 84, 110}, + {6, 30, 58, 86, 114}, + {6, 34, 62, 90, 118}, + {6, 26, 50, 74, 98, 122}, + {6, 30, 54, 78, 102, 126}, + {6, 26, 52, 78, 104, 130}, + {6, 30, 56, 82, 108, 134}, + {6, 34, 60, 86, 112, 138}, + {6, 30, 58, 86, 114, 142}, + {6, 34, 62, 90, 118, 146}, + {6, 30, 54, 78, 102, 126, 150}, + {6, 24, 50, 76, 102, 128, 154}, + {6, 28, 54, 80, 106, 132, 158}, + {6, 32, 58, 84, 110, 136, 162}, + {6, 26, 54, 82, 110, 138, 166}, + {6, 30, 58, 86, 114, 142, 170}, +}; + +// Return n-th bit of arr starting from MSB. +constexpr uint8_t get_bit_r(uint8_t* arr, int n) { + return (arr[n >> 3] >> (7 - (n & 7))) & 1; +} + +// Add up to 16 bits to arr. Data starts from MSB as well as each byte of an +// array. +constexpr void add_bits(uint16_t data, int n, uint8_t* arr, size_t& pos) { + while (n--) { + arr[pos >> 3] |= ((data >> n) & 1) << (7 - (pos & 7)); + ++pos; + } +} + +// Translate char to alphanumeric encoding value, +constexpr int alphanumeric(char c) { + if (c >= '0' && c <= '9') return c - '0'; + + if (c >= 'A' && c <= 'Z') return c - 'A' + 10; + + switch (c) { + case ' ': + return 36; + case '$': + return 37; + case '%': + return 38; + case '*': + return 39; + case '+': + return 40; + case '-': + return 41; + case '.': + return 42; + case '/': + return 43; + case ':': + return 44; + } + return -1; +} + +// Check if string can be encoded in alphanumeric mode. +constexpr bool is_alphanumeric(const char* str, size_t len) { + for (size_t i = 0; i < len; ++i) + if (alphanumeric(str[i]) == -1) return false; + return true; +} + +// Check if string can be encoded in numeric mode. +constexpr bool is_numeric(const char* str, size_t len) { + for (size_t i = 0; i < len; ++i) + if (str[i] < '0' || str[i] > '9') return false; + return true; +} + +// Check if string can be encoded in kanji mode. +constexpr bool is_kanji(const char* str, size_t len) { + for (size_t i = 0; i < len; i += 2) { + uint16_t val = uint16_t(str[i]) | (uint16_t(str[i + 1]) << 8); + if (val < 0x8140 || val > 0xebbf || (val > 0x9ffc && val < 0xe040)) return false; + } + return true; +} + +// Reed-Solomon Ecc generator polynomial for the given degree. +constexpr void gf_gen_poly(int degree, uint8_t* poly) { + SetMem(poly, 0, degree); + + uint8_t root = poly[degree - 1] = 1; + + for (int i = 0; i < degree; ++i) { + for (int j = 0; j < degree - 1; ++j) poly[j] = gf_mul(poly[j], root) ^ poly[j + 1]; + poly[degree - 1] = gf_mul(poly[degree - 1], root); + root = (root << 1) ^ ((root >> 7) * 0x11d); + } +} + +// Polynomial division if Galois Field. +constexpr void gf_poly_div(uint8_t* dividend, size_t len, uint8_t* divisor, int degree, + uint8_t* result) { + SetMem(result, 0, degree); + + for (size_t i = 0; i < len; ++i) { + uint8_t factor = dividend[i] ^ result[0]; + MoveMem(&result[0], &result[1], degree - 1); + result[degree - 1] = 0; + for (int j = 0; j < degree; ++j) result[j] ^= gf_mul(divisor[j], factor); + } +} + +enum Ecc { + L, + M, + Q, + H, +}; + +enum Mode { + M_NUMERIC, + M_ALPHANUMERIC, + M_BYTE, + M_KANJI, +}; + +// Select appropriate encoding mode for string. +constexpr Mode select_mode(const char* str, size_t len) { + if (is_numeric(str, len)) return M_NUMERIC; + if (is_alphanumeric(str, len)) return M_ALPHANUMERIC; + if (is_kanji(str, len)) return M_KANJI; + return M_BYTE; +} + +// Return size of Character Control Indicator in bits for given version and +// mode. +constexpr int cci(int ver, Mode mode) { + constexpr int cnt[4][3] = { + {10, 12, 14}, + {9, 11, 13}, + {8, 16, 16}, + {8, 10, 12}, + }; + if (ver < 10) return cnt[mode][0]; + if (ver < 27) return cnt[mode][1]; + return cnt[mode][2]; +} + +template <int V> +struct Qr { + private: + friend class QrDelegate; + bool draw(int x, int y) noexcept; + + public: + constexpr auto side_size() const { return SIDE; } + + bool module(int x, int y); + bool encode(const char* str, size_t len, Ecc ecc, int mask = -1); + + private: + bool encode_data(const char* data, size_t len, Ecc ecc, uint8_t* out); + void encode_ecc(uint8_t* data, Ecc ecc, uint8_t* out); + + void add_data(uint8_t* data, uint8_t* patterns); + void add_patterns(); + void add_version(); + void add_format(Ecc ecc, int mask); + void reserve_patterns(uint8_t* out); + + template <bool Black> + void draw_rect(int y, int x, int height, int width, uint8_t* out); + template <bool Black> + void draw_bound(int y, int x, int height, int width, uint8_t* out); + + template <bool Horizontal> + int rule_1_3_score(); + int penalty_score(); + int select_mask(Ecc ecc, uint8_t* patterns); + void apply_mask(int mask, uint8_t* patterns); + + private: + static_assert(V >= 1 && V <= 40, "invalid version"); + static constexpr int SIDE = 17 + V * 4; + static constexpr int N_BITS = SIDE * SIDE; + static constexpr int N_ALIGN = V == 1 ? 0 : V / 7 + 2; + static constexpr int N_ALIGN_BITS = V > 1 ? (N_ALIGN* N_ALIGN - 3) * 25 : 0; + static constexpr int N_TIMING_BITS = (SIDE - 16) * 2 - (10 * (V > 1 ? N_ALIGN - 2 : 0)); + static constexpr int N_VER_BITS = V > 6 ? 36 : 0; + static constexpr int N_DAT_BITS = N_BITS - (192 + N_ALIGN_BITS + N_TIMING_BITS + 31 + N_VER_BITS); + static constexpr int N_BYTES = utl::bytes_in_bits(N_BITS); // Actual number of bytes_in_bits + // required to store whole Qr code + static constexpr int N_DAT_BYTES = + utl::bytes_in_bits(N_DAT_BITS); // Actual number of bytes_in_bits required to store + // [data + ecc] + static constexpr int N_DAT_CAPACITY = + N_DAT_BITS >> 3; // Capacity of [data + ecc] without remainder bits + private: + /// @brief internal function to retrieve bit from a bitset. + uint8_t get_arr_bit(uint8_t* arr, unsigned bit) const { return utl::get_arr_bit(arr, bit); } + + /// @brief internal function to set bit from a bitset. + void set_arr_bit(uint8_t* arr, unsigned bit) { utl::set_arr_bit(arr, bit); } + + /// @brief internal function to clear bit from a bitset. + void clr_arr_bit(uint8_t* arr, unsigned bit) { utl::clr_arr_bit(arr, bit); } + + uint8_t code[N_BYTES] = {}; + + bool status = false; +}; + +// Get color of a module from left-to-right and top-to-bottom. Black is true. +template <int V> +bool Qr<V>::module(int x, int y) { + return get_arr_bit(code, y * SIDE + x); +} + +/// @brief draw a new QR code. +template <int V> +bool Qr<V>::draw(int whereX, int whereY) noexcept { + if (!this->status) return false; // it may be invalid. + + fb_init(); + + for (int y = 0; y < (this->side_size()); ++y) { + for (int x = 0; x < (this->side_size()); ++x) { + FBDrawInRegion((this->module(x, y) ? RGB(00, 00, 00) : RGB(0xFF, 0xFF, 0xFF)), 1, 1, + x + whereX, y + whereY); + } + } + + fb_clear(); + + return false; +} + +// Create Qr code with given error correction level. If mask == -1, +// then best mask selected automatically. NOTE: Automatic mask is the +// most expensive operation. Takes about 95 % of all computation time. +template <int V> +bool Qr<V>::encode(const char* str, size_t len, Ecc ecc, int mask) { + uint8_t data[N_DAT_BYTES] = {}; + uint8_t data_with_ecc[N_DAT_BYTES] = {}; + uint8_t patterns[N_BYTES] = {}; + + if (!encode_data(str, len, ecc, data)) { + return status = false; + } + + encode_ecc(data, ecc, data_with_ecc); + + reserve_patterns(patterns); + CopyMem(code, patterns, N_BYTES); + + add_data(data_with_ecc, patterns); + add_patterns(); + add_version(); + + mask = mask != -1 ? mask & 7 : select_mask(ecc, patterns); + + add_format(ecc, mask); + apply_mask(mask, patterns); + + return status = true; +} + +template <int V> +bool Qr<V>::encode_data(const char* data, size_t len, Ecc ecc, uint8_t* out) { + Mode mode = select_mode(data, len); + + size_t n_bits = (N_DAT_CAPACITY - ECC_CODEWORDS_PER_BLOCK[ecc][V] * N_ECC_BLOCKS[ecc][V]) << 3; + size_t pos = 0; + + add_bits(1 << mode, 4, out, pos); + add_bits(len, cci(V, mode), out, pos); + + if (mode == M_NUMERIC) { + const size_t triplets = len / 3; + const size_t triplets_size = triplets * 3; + const size_t rem = len % 3; + const size_t rem_bits = rem == 2 ? 7 : rem == 1 ? 4 : 0; + const size_t total_size = 10 * triplets + rem_bits; + + if (pos + total_size > n_bits) return false; + + char buf[4] = {}; + + for (size_t i = 0; i < triplets_size; i += 3) { + buf[0] = data[i]; + buf[1] = data[i + 1]; + buf[2] = data[i + 2]; + + uint16_t num = StringToLong(buf, NULL, 10); + add_bits(num, 10, out, pos); + } + + if (rem) { + buf[0] = data[triplets_size]; + buf[1] = data[triplets_size + 1]; + buf[rem] = 0; + + uint16_t num = StringToLong(buf, NULL, 10); + add_bits(num, rem_bits, out, pos); + } + } else if (mode == M_ALPHANUMERIC) { + if (pos + 11 * (int(len & ~1ul) / 2) > n_bits) return false; + + for (int i = 0; i < int(len & ~1ul); i += 2) { + uint16_t num = alphanumeric(data[i]) * 45 + alphanumeric(data[i + 1]); + add_bits(num, 11, out, pos); + } + if (len & 1) { + if (pos + 6 > n_bits) return false; + + add_bits(alphanumeric(data[len - 1]), 6, out, pos); + } + } else if (mode == M_BYTE) { + if (pos + len * 8 > n_bits) return false; + + for (size_t i = 0; i < len; ++i) add_bits(data[i], 8, out, pos); + } else { + if (pos + 13 * (len / 2) > n_bits) return false; + + for (size_t i = 0; i < len; i += 2) { + uint16_t val = ((uint8_t) data[i]) | (((uint8_t) data[i + 1]) << 8); + uint16_t res = 0; + val -= val < 0x9FFC ? 0x8140 : 0xC140; + res += val & 0xff; + res += (val >> 8) * 0xc0; + add_bits(res, 13, out, pos); + } + } + + size_t padding = n_bits - pos; + size_t i = 0; + + add_bits(0, padding > 4 ? 4 : padding, out, pos); + + if (pos & 7) add_bits(0, (8 - pos) & 7, out, pos); + + while (pos < n_bits) add_bits(++i & 1 ? 0xec : 0x11, 8, out, pos); + + return true; +} + +template <int V> +void Qr<V>::encode_ecc(uint8_t* data, Ecc ecc, uint8_t* out) { + int n_blocks = N_ECC_BLOCKS[ecc][V]; + int ecc_len = ECC_CODEWORDS_PER_BLOCK[ecc][V]; + + int n_data_bytes = N_DAT_CAPACITY - ecc_len * n_blocks; + + int n_short_blocks = n_blocks - N_DAT_CAPACITY % n_blocks; + int short_len = N_DAT_CAPACITY / n_blocks - ecc_len; + + uint8_t gen_poly[30]; + uint8_t ecc_buf[30]; + + gf_gen_poly(ecc_len, gen_poly); + + uint8_t* data_ptr = data; + + for (int i = 0; i < n_blocks; ++i) { + int data_len = short_len; + + if (i >= n_short_blocks) ++data_len; + + gf_poly_div(data_ptr, data_len, gen_poly, ecc_len, ecc_buf); -/// @note the QR code is still code 128, it utilizes the same concept of having it's own character set. - -namespace qr -{ - inline uint8_t min_poly = - 0b11101, /* Minimal polynomial x^8 + x^4 + x^3 + x^2 + 1 */ - generator = 0b10; /* Generator of Galois field */ - - /// @brief galois finite field multiplication. - inline uint8_t gf_mul(uint8_t a, uint8_t b) - { - uint8_t res = 0; - - for (; b; b >>= 1) - { - if (b & 1) - res ^= a; - if (a & 0x80) - a = (a << 1) ^ min_poly; - else - a <<= 1; - } - - return res; - } - - // Size of Ecc block with respect to level and version. 0 version is for - // padding. - constexpr int ECC_CODEWORDS_PER_BLOCK[4][41] = { - {0, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, - 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, - {0, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, - 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, - {0, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, - 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, - {0, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, - 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, - }; - - // Number of Ecc blocks with respect to level and version. 0 version is for - // padding. - constexpr int N_ECC_BLOCKS[4][41] = { - {0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, - 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, - 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, - {0, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, - 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, - 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, - {0, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, - 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, - 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, - {0, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, - 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, - 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, - }; - - // Positions of central modules of alignment patterns according to version. 0 - // version is for padding. - constexpr int ALIGN_POS[41][7] = { - {}, - {0}, - {6, 18}, - {6, 22}, - {6, 26}, - {6, 30}, - {6, 34}, - {6, 22, 38}, - {6, 24, 42}, - {6, 26, 46}, - {6, 28, 50}, - {6, 30, 54}, - {6, 32, 58}, - {6, 34, 62}, - {6, 26, 46, 66}, - {6, 26, 48, 70}, - {6, 26, 50, 74}, - {6, 30, 54, 78}, - {6, 30, 56, 82}, - {6, 30, 58, 86}, - {6, 34, 62, 90}, - {6, 28, 50, 72, 94}, - {6, 26, 50, 74, 98}, - {6, 30, 54, 78, 102}, - {6, 28, 54, 80, 106}, - {6, 32, 58, 84, 110}, - {6, 30, 58, 86, 114}, - {6, 34, 62, 90, 118}, - {6, 26, 50, 74, 98, 122}, - {6, 30, 54, 78, 102, 126}, - {6, 26, 52, 78, 104, 130}, - {6, 30, 56, 82, 108, 134}, - {6, 34, 60, 86, 112, 138}, - {6, 30, 58, 86, 114, 142}, - {6, 34, 62, 90, 118, 146}, - {6, 30, 54, 78, 102, 126, 150}, - {6, 24, 50, 76, 102, 128, 154}, - {6, 28, 54, 80, 106, 132, 158}, - {6, 32, 58, 84, 110, 136, 162}, - {6, 26, 54, 82, 110, 138, 166}, - {6, 30, 58, 86, 114, 142, 170}, - }; - - // Return n-th bit of arr starting from MSB. - constexpr uint8_t get_bit_r(uint8_t* arr, int n) - { - return (arr[n >> 3] >> (7 - (n & 7))) & 1; - } - - // Add up to 16 bits to arr. Data starts from MSB as well as each byte of an - // array. - constexpr void add_bits(uint16_t data, int n, uint8_t* arr, size_t& pos) - { - while (n--) - { - arr[pos >> 3] |= ((data >> n) & 1) << (7 - (pos & 7)); - ++pos; - } - } - - // Translate char to alphanumeric encoding value, - constexpr int alphanumeric(char c) - { - if (c >= '0' && c <= '9') - return c - '0'; - - if (c >= 'A' && c <= 'Z') - return c - 'A' + 10; - - switch (c) - { - case ' ': - return 36; - case '$': - return 37; - case '%': - return 38; - case '*': - return 39; - case '+': - return 40; - case '-': - return 41; - case '.': - return 42; - case '/': - return 43; - case ':': - return 44; - } - return -1; - } - - // Check if string can be encoded in alphanumeric mode. - constexpr bool is_alphanumeric(const char* str, size_t len) - { - for (size_t i = 0; i < len; ++i) - if (alphanumeric(str[i]) == -1) - return false; - return true; - } - - // Check if string can be encoded in numeric mode. - constexpr bool is_numeric(const char* str, size_t len) - { - for (size_t i = 0; i < len; ++i) - if (str[i] < '0' || str[i] > '9') - return false; - return true; - } - - // Check if string can be encoded in kanji mode. - constexpr bool is_kanji(const char* str, size_t len) - { - for (size_t i = 0; i < len; i += 2) - { - uint16_t val = uint16_t(str[i]) | (uint16_t(str[i + 1]) << 8); - if (val < 0x8140 || val > 0xebbf || (val > 0x9ffc && val < 0xe040)) - return false; - } - return true; - } - - // Reed-Solomon Ecc generator polynomial for the given degree. - constexpr void gf_gen_poly(int degree, uint8_t* poly) - { - SetMem(poly, 0, degree); - - uint8_t root = poly[degree - 1] = 1; - - for (int i = 0; i < degree; ++i) - { - for (int j = 0; j < degree - 1; ++j) - poly[j] = gf_mul(poly[j], root) ^ poly[j + 1]; - poly[degree - 1] = gf_mul(poly[degree - 1], root); - root = (root << 1) ^ ((root >> 7) * 0x11d); - } - } - - // Polynomial division if Galois Field. - constexpr void gf_poly_div(uint8_t* dividend, size_t len, uint8_t* divisor, int degree, uint8_t* result) - { - SetMem(result, 0, degree); - - for (size_t i = 0; i < len; ++i) - { - uint8_t factor = dividend[i] ^ result[0]; - MoveMem(&result[0], &result[1], degree - 1); - result[degree - 1] = 0; - for (int j = 0; j < degree; ++j) - result[j] ^= gf_mul(divisor[j], factor); - } - } - - enum Ecc - { - L, - M, - Q, - H, - }; - - enum Mode - { - M_NUMERIC, - M_ALPHANUMERIC, - M_BYTE, - M_KANJI, - }; - - // Select appropriate encoding mode for string. - constexpr Mode select_mode(const char* str, size_t len) - { - if (is_numeric(str, len)) - return M_NUMERIC; - if (is_alphanumeric(str, len)) - return M_ALPHANUMERIC; - if (is_kanji(str, len)) - return M_KANJI; - return M_BYTE; - } - - // Return size of Character Control Indicator in bits for given version and - // mode. - constexpr int cci(int ver, Mode mode) - { - constexpr int cnt[4][3] = { - {10, 12, 14}, - {9, 11, 13}, - {8, 16, 16}, - {8, 10, 12}, - }; - if (ver < 10) - return cnt[mode][0]; - if (ver < 27) - return cnt[mode][1]; - return cnt[mode][2]; - } - - template <int V> - struct Qr - { - private: - friend class QrDelegate; - bool draw(int x, int y) noexcept; - - public: - constexpr auto side_size() const - { - return SIDE; - } - - bool module(int x, int y); - bool encode(const char* str, size_t len, Ecc ecc, int mask = -1); - - private: - bool encode_data(const char* data, size_t len, Ecc ecc, uint8_t* out); - void encode_ecc(uint8_t* data, Ecc ecc, uint8_t* out); - - void add_data(uint8_t* data, uint8_t* patterns); - void add_patterns(); - void add_version(); - void add_format(Ecc ecc, int mask); - void reserve_patterns(uint8_t* out); - - template <bool Black> - void draw_rect(int y, int x, int height, int width, uint8_t* out); - template <bool Black> - void draw_bound(int y, int x, int height, int width, uint8_t* out); - - template <bool Horizontal> - int rule_1_3_score(); - int penalty_score(); - int select_mask(Ecc ecc, uint8_t* patterns); - void apply_mask(int mask, uint8_t* patterns); - - private: - static_assert(V >= 1 && V <= 40, "invalid version"); - static constexpr int SIDE = 17 + V * 4; - static constexpr int N_BITS = SIDE * SIDE; - static constexpr int N_ALIGN = V == 1 ? 0 : V / 7 + 2; - static constexpr int N_ALIGN_BITS = V > 1 ? (N_ALIGN* N_ALIGN - 3) * 25 : 0; - static constexpr int N_TIMING_BITS = - (SIDE - 16) * 2 - (10 * (V > 1 ? N_ALIGN - 2 : 0)); - static constexpr int N_VER_BITS = V > 6 ? 36 : 0; - static constexpr int N_DAT_BITS = - N_BITS - (192 + N_ALIGN_BITS + N_TIMING_BITS + 31 + N_VER_BITS); - static constexpr int N_BYTES = utl::bytes_in_bits(N_BITS); // Actual number of bytes_in_bits - // required to store whole Qr code - static constexpr int N_DAT_BYTES = utl::bytes_in_bits(N_DAT_BITS); // Actual number of bytes_in_bits required to store - // [data + ecc] - static constexpr int N_DAT_CAPACITY = - N_DAT_BITS >> 3; // Capacity of [data + ecc] without remainder bits - private: - /// @brief internal function to retrieve bit from a bitset. - uint8_t get_arr_bit(uint8_t* arr, unsigned bit) const - { - return utl::get_arr_bit(arr, bit); - } - - /// @brief internal function to set bit from a bitset. - void set_arr_bit(uint8_t* arr, unsigned bit) - { - utl::set_arr_bit(arr, bit); - } - - /// @brief internal function to clear bit from a bitset. - void clr_arr_bit(uint8_t* arr, unsigned bit) - { - utl::clr_arr_bit(arr, bit); - } - - uint8_t code[N_BYTES] = {}; - - bool status = false; - }; - - // Get color of a module from left-to-right and top-to-bottom. Black is true. - template <int V> - bool Qr<V>::module(int x, int y) - { - return get_arr_bit(code, y * SIDE + x); - } - - /// @brief draw a new QR code. - template <int V> - bool Qr<V>::draw(int whereX, int whereY) noexcept - { - if (!this->status) - return false; // it may be invalid. - - fb_init(); - - for (int y = 0; y < (this->side_size()); ++y) - { - for (int x = 0; x < (this->side_size()); ++x) - { - FBDrawInRegion( - (this->module(x, y) ? RGB(00, 00, 00) : RGB(0xFF, 0xFF, 0xFF)), - 1, 1, - x + whereX, y + whereY); - } - } - - fb_clear(); - - return false; - } - - // Create Qr code with given error correction level. If mask == -1, - // then best mask selected automatically. NOTE: Automatic mask is the - // most expensive operation. Takes about 95 % of all computation time. - template <int V> - bool Qr<V>::encode(const char* str, size_t len, Ecc ecc, int mask) - { - uint8_t data[N_DAT_BYTES] = {}; - uint8_t data_with_ecc[N_DAT_BYTES] = {}; - uint8_t patterns[N_BYTES] = {}; - - if (!encode_data(str, len, ecc, data)) - { - return status = false; - } - - encode_ecc(data, ecc, data_with_ecc); - - reserve_patterns(patterns); - CopyMem(code, patterns, N_BYTES); - - add_data(data_with_ecc, patterns); - add_patterns(); - add_version(); - - mask = mask != -1 ? mask & 7 : select_mask(ecc, patterns); - - add_format(ecc, mask); - apply_mask(mask, patterns); - - return status = true; - } - - template <int V> - bool Qr<V>::encode_data(const char* data, size_t len, Ecc ecc, uint8_t* out) - { - Mode mode = select_mode(data, len); - - size_t n_bits = - (N_DAT_CAPACITY - ECC_CODEWORDS_PER_BLOCK[ecc][V] * N_ECC_BLOCKS[ecc][V]) - << 3; - size_t pos = 0; - - add_bits(1 << mode, 4, out, pos); - add_bits(len, cci(V, mode), out, pos); - - if (mode == M_NUMERIC) - { - const size_t triplets = len / 3; - const size_t triplets_size = triplets * 3; - const size_t rem = len % 3; - const size_t rem_bits = rem == 2 ? 7 : rem == 1 ? 4 - : 0; - const size_t total_size = 10 * triplets + rem_bits; - - if (pos + total_size > n_bits) - return false; - - char buf[4] = {}; - - for (size_t i = 0; i < triplets_size; i += 3) - { - buf[0] = data[i]; - buf[1] = data[i + 1]; - buf[2] = data[i + 2]; - - uint16_t num = StringToLong(buf, NULL, 10); - add_bits(num, 10, out, pos); - } - - if (rem) - { - buf[0] = data[triplets_size]; - buf[1] = data[triplets_size + 1]; - buf[rem] = 0; - - uint16_t num = StringToLong(buf, NULL, 10); - add_bits(num, rem_bits, out, pos); - } - } - else if (mode == M_ALPHANUMERIC) - { - if (pos + 11 * (int(len & ~1ul) / 2) > n_bits) - return false; - - for (int i = 0; i < int(len & ~1ul); i += 2) - { - uint16_t num = alphanumeric(data[i]) * 45 + alphanumeric(data[i + 1]); - add_bits(num, 11, out, pos); - } - if (len & 1) - { - if (pos + 6 > n_bits) - return false; - - add_bits(alphanumeric(data[len - 1]), 6, out, pos); - } - } - else if (mode == M_BYTE) - { - if (pos + len * 8 > n_bits) - return false; - - for (size_t i = 0; i < len; ++i) - add_bits(data[i], 8, out, pos); - } - else - { - if (pos + 13 * (len / 2) > n_bits) - return false; - - for (size_t i = 0; i < len; i += 2) - { - uint16_t val = ((uint8_t)data[i]) | (((uint8_t)data[i + 1]) << 8); - uint16_t res = 0; - val -= val < 0x9FFC ? 0x8140 : 0xC140; - res += val & 0xff; - res += (val >> 8) * 0xc0; - add_bits(res, 13, out, pos); - } - } - - size_t padding = n_bits - pos; - size_t i = 0; - - add_bits(0, padding > 4 ? 4 : padding, out, pos); - - if (pos & 7) - add_bits(0, (8 - pos) & 7, out, pos); - - while (pos < n_bits) - add_bits(++i & 1 ? 0xec : 0x11, 8, out, pos); - - return true; - } - - template <int V> - void Qr<V>::encode_ecc(uint8_t* data, Ecc ecc, uint8_t* out) - { - int n_blocks = N_ECC_BLOCKS[ecc][V]; - int ecc_len = ECC_CODEWORDS_PER_BLOCK[ecc][V]; - - int n_data_bytes = N_DAT_CAPACITY - ecc_len * n_blocks; - - int n_short_blocks = n_blocks - N_DAT_CAPACITY % n_blocks; - int short_len = N_DAT_CAPACITY / n_blocks - ecc_len; - - uint8_t gen_poly[30]; - uint8_t ecc_buf[30]; - - gf_gen_poly(ecc_len, gen_poly); - - uint8_t* data_ptr = data; - - for (int i = 0; i < n_blocks; ++i) - { - int data_len = short_len; - - if (i >= n_short_blocks) - ++data_len; - - gf_poly_div(data_ptr, data_len, gen_poly, ecc_len, ecc_buf); - - for (int j = 0, k = i; j < data_len; ++j, k += n_blocks) - { - if (j == short_len) - k -= n_short_blocks; - out[k] = data_ptr[j]; - } - for (int j = 0, k = n_data_bytes + i; j < ecc_len; ++j, k += n_blocks) - out[k] = ecc_buf[j]; - - data_ptr += data_len; - } - } - - template <int V> - void Qr<V>::add_data(uint8_t* data, uint8_t* patterns) - { - int data_pos = 0; - - for (int x = SIDE - 1; x >= 1; x -= 2) - { - if (x == 6) - x = 5; - - for (int i = 0; i < SIDE; ++i) - { - int y = !((x + 1) & 2) ? SIDE - 1 - i : i; - int coord = y * SIDE + x; - - if (!get_arr_bit(patterns, coord)) - { - if (get_bit_r(data, data_pos)) - set_arr_bit(code, coord); - - ++data_pos; - } - - if (!get_arr_bit(patterns, coord - 1)) - { - if (get_bit_r(data, data_pos)) - set_arr_bit(code, coord - 1); - - ++data_pos; - } - } - } - } - - template <int V> - void Qr<V>::add_patterns() - { - // White bounds inside finders - draw_bound<false>(1, 1, 5, 5, code); - draw_bound<false>(1, SIDE - 6, 5, 5, code); - draw_bound<false>(SIDE - 6, 1, 5, 5, code); - - // Finish alignment patterns - for (int i = 0; i < N_ALIGN; ++i) - { - for (int j = 0; j < N_ALIGN; ++j) - { - if ((!i && !j) || (!i && j == N_ALIGN - 1) || (!j && i == N_ALIGN - 1)) - continue; - draw_bound<false>(ALIGN_POS[V][i] - 1, ALIGN_POS[V][j] - 1, 3, 3, code); - } - } - - // Draw white separators - draw_rect<false>(7, 0, 1, 8, code); - draw_rect<false>(0, 7, 8, 1, code); - draw_rect<false>(SIDE - 8, 0, 1, 8, code); - draw_rect<false>(SIDE - 8, 7, 8, 1, code); - draw_rect<false>(7, SIDE - 8, 1, 8, code); - draw_rect<false>(0, SIDE - 8, 8, 1, code); - - // Perforate timing patterns - for (int i = 7; i < SIDE - 7; i += 2) - { - clr_arr_bit(code, 6 * SIDE + i); - clr_arr_bit(code, i * SIDE + 6); - } - } - - template <int V> - void Qr<V>::add_version() - { - if (V < 7) - return; - - uint32_t rem = V; - - for (uint8_t i = 0; i < 12; ++i) - rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); - - uint32_t data = V << 12 | rem; - - for (int x = 0; x < 6; ++x) - { - for (int j = 0; j < 3; ++j) - { - int y = SIDE - 11 + j; - - bool black = (data >> (x * 3 + j)) & 1; - - if (!black) - { - clr_arr_bit(code, y * SIDE + x); - clr_arr_bit(code, y + SIDE * x); - } - } - } - } - - template <int V> - void Qr<V>::add_format(Ecc ecc, int mask) - { - int data = (ecc ^ 1) << 3 | mask; - int rem = data; - - for (int i = 0; i < 10; i++) - rem = (rem << 1) ^ ((rem >> 9) * 0b10100110111); - - int res = (data << 10 | rem) ^ 0b101010000010010; - - for (int i = 0; i < 6; ++i) - { - if ((res >> i) & 1) - { - set_arr_bit(code, SIDE * 8 + SIDE - 1 - i); - set_arr_bit(code, SIDE * i + 8); - } - else - { - clr_arr_bit(code, SIDE * 8 + SIDE - 1 - i); - clr_arr_bit(code, SIDE * i + 8); - } - } - - for (int i = 6; i < 8; ++i) - { - if ((res >> i) & 1) - { - set_arr_bit(code, SIDE * 8 + SIDE - 1 - i); - set_arr_bit(code, SIDE * (i + 1) + 8); - } - else - { - clr_arr_bit(code, SIDE * 8 + SIDE - 1 - i); - clr_arr_bit(code, SIDE * (i + 1) + 8); - } - } - - if ((res >> 8) & 1) - { - set_arr_bit(code, SIDE * 8 + 7); - set_arr_bit(code, SIDE * (SIDE - 7) + 8); - } - else - { - clr_arr_bit(code, SIDE * 8 + 7); - clr_arr_bit(code, SIDE * (SIDE - 7) + 8); - } - - for (int i = 9, j = 5; i < 15; ++i, --j) - { - if ((res >> i) & 1) - { - set_arr_bit(code, SIDE * 8 + j); - set_arr_bit(code, SIDE * (SIDE - 1 - j) + 8); - } - else - { - clr_arr_bit(code, SIDE * 8 + j); - clr_arr_bit(code, SIDE * (SIDE - 1 - j) + 8); - } - } - } - - template <int V> - template <bool B> - void Qr<V>::draw_rect(int y, int x, int height, int width, uint8_t* out) - { - if (B) - { - for (int dy = y * SIDE; dy < (y + height) * SIDE; dy += SIDE) - for (int dx = x; dx < x + width; ++dx) - set_arr_bit(out, dy + dx); - } - else - { - for (int dy = y * SIDE; dy < (y + height) * SIDE; dy += SIDE) - for (int dx = x; dx < x + width; ++dx) - clr_arr_bit(out, dy + dx); - } - } - - template <int V> - template <bool B> - void Qr<V>::draw_bound(int y, int x, int height, int width, uint8_t* out) - { - if (B) - { - for (int i = y * SIDE + x; i < y * SIDE + x + width; ++i) - set_arr_bit(out, i); - for (int i = (y + height - 1) * SIDE + x; - i < (y + height - 1) * SIDE + x + width; ++i) - set_arr_bit(out, i); - for (int i = (y + 1) * SIDE + x; i < (y + height - 1) * SIDE + x; i += SIDE) - set_arr_bit(out, i); - for (int i = (y + 1) * SIDE + x + width - 1; - i < (y + height - 1) * SIDE + x + width - 1; i += SIDE) - set_arr_bit(out, i); - } - else - { - for (int i = y * SIDE + x; i < y * SIDE + x + width; ++i) - clr_arr_bit(out, i); - for (int i = (y + height - 1) * SIDE + x; - i < (y + height - 1) * SIDE + x + width; ++i) - clr_arr_bit(out, i); - for (int i = (y + 1) * SIDE + x; i < (y + height - 1) * SIDE + x; i += SIDE) - clr_arr_bit(out, i); - for (int i = (y + 1) * SIDE + x + width - 1; - i < (y + height - 1) * SIDE + x + width - 1; i += SIDE) - clr_arr_bit(out, i); - } - } - - template <int V> - void Qr<V>::reserve_patterns(uint8_t* out) - { - draw_rect<true>(0, 6, SIDE, 1, out); - draw_rect<true>(6, 0, 1, SIDE, out); - - draw_rect<true>(0, 0, 9, 9, out); - draw_rect<true>(SIDE - 8, 0, 8, 9, out); - draw_rect<true>(0, SIDE - 8, 9, 8, out); - - for (int i = 0; i < N_ALIGN; ++i) - { - for (int j = 0; j < N_ALIGN; ++j) - { - if ((!i && !j) || (!i && j == N_ALIGN - 1) || (!j && i == N_ALIGN - 1)) - continue; - draw_rect<true>(ALIGN_POS[V][i] - 2, ALIGN_POS[V][j] - 2, 5, 5, out); - } - } - - if (V >= 7) - { - draw_rect<true>(SIDE - 11, 0, 3, 6, out); - draw_rect<true>(0, SIDE - 11, 6, 3, out); - } - } - - template <int V> - template <bool H> - int Qr<V>::rule_1_3_score() - { - constexpr int y_max = H ? N_BITS : SIDE; - constexpr int x_max = H ? SIDE : N_BITS; - constexpr int y_step = H ? SIDE : 1; - constexpr int x_step = H ? 1 : SIDE; - - int res = 0; - - for (int y = 0; y < y_max; y += y_step) - { - bool color = get_arr_bit(code, y); - int finder = color; - int cnt = 1; - for (int x = 1; x < x_max; x += x_step) - { - if (get_arr_bit(code, y + x) == color) - { - ++cnt; - if (cnt == 5) - res += 3; - if (cnt > 5) - ++res; - } - else - { - color = !color; - cnt = 1; - } - // Finder-like - finder = ((finder << 1) & 0x7ff) | color; - if (x >= x_step * 10) - { - if (finder == 0x05d || finder == 0x5d0) - res += 40; - } - } - } - return res; - } - - template <int V> - int Qr<V>::penalty_score() - { - int res = 0; - - res += rule_1_3_score<true>(); - res += rule_1_3_score<false>(); - - for (int y = 0; y < N_BITS - SIDE; y += SIDE) - { - for (int x = 0; x < SIDE - 1; ++x) - { - bool c = get_arr_bit(code, y + x); - - if (c == get_arr_bit(code, y + x + 1) && - c == get_arr_bit(code, y + x + SIDE) && - c == get_arr_bit(code, y + x + SIDE + 1)) - res += 3; - } - } - - int black = 0; - for (int y = 0; y < N_BITS; y += SIDE) - { - for (int x = 0; x < SIDE; ++x) - black += get_arr_bit(code, y + x); - } - res += abs((black * 100) / N_BITS - 50) / 5 * 10; - - return res; - } - - template <int V> - int Qr<V>::select_mask(Ecc ecc, uint8_t* patterns) - { - unsigned min_score = -1; - unsigned score = 0; - uint8_t mask = 0; - - for (int i = 0; i < 8; ++i) - { - add_format(ecc, i); - apply_mask(i, patterns); - score = penalty_score(); - if (score < min_score) - { - mask = i; - min_score = score; - } - apply_mask(i, patterns); - } - return mask; - } - - template <int V> - void Qr<V>::apply_mask(int mask, uint8_t* patterns) - { - for (int y = 0, dy = 0; y < SIDE; ++y, dy += SIDE) - { - for (int x = 0; x < SIDE; ++x) - { - int coord = dy + x; - - if (get_arr_bit(patterns, coord)) - continue; - - bool keep = true; - - switch (mask) - { - case 0: - keep = (x + y) & 1; - break; - case 1: - keep = y & 1; - break; - case 2: - keep = x % 3; - break; - case 3: - keep = (x + y) % 3; - break; - case 4: - keep = (y / 2 + x / 3) & 1; - break; - case 5: - keep = x * y % 2 + x * y % 3; - break; - case 6: - keep = (x * y % 2 + x * y % 3) & 1; - break; - case 7: - keep = ((x + y) % 2 + x * y % 3) & 1; - break; - } - - if (!keep) - { - if (get_arr_bit(code, coord)) - clr_arr_bit(code, coord); - else - set_arr_bit(code, coord); - } - } - } - } - - /// @brief QR code encoder class. - class QrDelegate final - { - public: - explicit QrDelegate() = default; - ~QrDelegate() = default; - - NE_COPY_DEFAULT(QrDelegate) - - /// @brief Draw method delegate. - template <Int32 V> - bool draw(Qr<V>& subject, Int32 x, Int32 y) noexcept - { - return subject.draw(x, y); - } - }; -} // namespace qr - -namespace Kernel::Qr -{ - using namespace qr; -} // namespace Kernel::Qr - -#endif // QR_H
\ No newline at end of file + for (int j = 0, k = i; j < data_len; ++j, k += n_blocks) { + if (j == short_len) k -= n_short_blocks; + out[k] = data_ptr[j]; + } + for (int j = 0, k = n_data_bytes + i; j < ecc_len; ++j, k += n_blocks) out[k] = ecc_buf[j]; + + data_ptr += data_len; + } +} + +template <int V> +void Qr<V>::add_data(uint8_t* data, uint8_t* patterns) { + int data_pos = 0; + + for (int x = SIDE - 1; x >= 1; x -= 2) { + if (x == 6) x = 5; + + for (int i = 0; i < SIDE; ++i) { + int y = !((x + 1) & 2) ? SIDE - 1 - i : i; + int coord = y * SIDE + x; + + if (!get_arr_bit(patterns, coord)) { + if (get_bit_r(data, data_pos)) set_arr_bit(code, coord); + + ++data_pos; + } + + if (!get_arr_bit(patterns, coord - 1)) { + if (get_bit_r(data, data_pos)) set_arr_bit(code, coord - 1); + + ++data_pos; + } + } + } +} + +template <int V> +void Qr<V>::add_patterns() { + // White bounds inside finders + draw_bound<false>(1, 1, 5, 5, code); + draw_bound<false>(1, SIDE - 6, 5, 5, code); + draw_bound<false>(SIDE - 6, 1, 5, 5, code); + + // Finish alignment patterns + for (int i = 0; i < N_ALIGN; ++i) { + for (int j = 0; j < N_ALIGN; ++j) { + if ((!i && !j) || (!i && j == N_ALIGN - 1) || (!j && i == N_ALIGN - 1)) continue; + draw_bound<false>(ALIGN_POS[V][i] - 1, ALIGN_POS[V][j] - 1, 3, 3, code); + } + } + + // Draw white separators + draw_rect<false>(7, 0, 1, 8, code); + draw_rect<false>(0, 7, 8, 1, code); + draw_rect<false>(SIDE - 8, 0, 1, 8, code); + draw_rect<false>(SIDE - 8, 7, 8, 1, code); + draw_rect<false>(7, SIDE - 8, 1, 8, code); + draw_rect<false>(0, SIDE - 8, 8, 1, code); + + // Perforate timing patterns + for (int i = 7; i < SIDE - 7; i += 2) { + clr_arr_bit(code, 6 * SIDE + i); + clr_arr_bit(code, i * SIDE + 6); + } +} + +template <int V> +void Qr<V>::add_version() { + if (V < 7) return; + + uint32_t rem = V; + + for (uint8_t i = 0; i < 12; ++i) rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); + + uint32_t data = V << 12 | rem; + + for (int x = 0; x < 6; ++x) { + for (int j = 0; j < 3; ++j) { + int y = SIDE - 11 + j; + + bool black = (data >> (x * 3 + j)) & 1; + + if (!black) { + clr_arr_bit(code, y * SIDE + x); + clr_arr_bit(code, y + SIDE * x); + } + } + } +} + +template <int V> +void Qr<V>::add_format(Ecc ecc, int mask) { + int data = (ecc ^ 1) << 3 | mask; + int rem = data; + + for (int i = 0; i < 10; i++) rem = (rem << 1) ^ ((rem >> 9) * 0b10100110111); + + int res = (data << 10 | rem) ^ 0b101010000010010; + + for (int i = 0; i < 6; ++i) { + if ((res >> i) & 1) { + set_arr_bit(code, SIDE * 8 + SIDE - 1 - i); + set_arr_bit(code, SIDE * i + 8); + } else { + clr_arr_bit(code, SIDE * 8 + SIDE - 1 - i); + clr_arr_bit(code, SIDE * i + 8); + } + } + + for (int i = 6; i < 8; ++i) { + if ((res >> i) & 1) { + set_arr_bit(code, SIDE * 8 + SIDE - 1 - i); + set_arr_bit(code, SIDE * (i + 1) + 8); + } else { + clr_arr_bit(code, SIDE * 8 + SIDE - 1 - i); + clr_arr_bit(code, SIDE * (i + 1) + 8); + } + } + + if ((res >> 8) & 1) { + set_arr_bit(code, SIDE * 8 + 7); + set_arr_bit(code, SIDE * (SIDE - 7) + 8); + } else { + clr_arr_bit(code, SIDE * 8 + 7); + clr_arr_bit(code, SIDE * (SIDE - 7) + 8); + } + + for (int i = 9, j = 5; i < 15; ++i, --j) { + if ((res >> i) & 1) { + set_arr_bit(code, SIDE * 8 + j); + set_arr_bit(code, SIDE * (SIDE - 1 - j) + 8); + } else { + clr_arr_bit(code, SIDE * 8 + j); + clr_arr_bit(code, SIDE * (SIDE - 1 - j) + 8); + } + } +} + +template <int V> +template <bool B> +void Qr<V>::draw_rect(int y, int x, int height, int width, uint8_t* out) { + if (B) { + for (int dy = y * SIDE; dy < (y + height) * SIDE; dy += SIDE) + for (int dx = x; dx < x + width; ++dx) set_arr_bit(out, dy + dx); + } else { + for (int dy = y * SIDE; dy < (y + height) * SIDE; dy += SIDE) + for (int dx = x; dx < x + width; ++dx) clr_arr_bit(out, dy + dx); + } +} + +template <int V> +template <bool B> +void Qr<V>::draw_bound(int y, int x, int height, int width, uint8_t* out) { + if (B) { + for (int i = y * SIDE + x; i < y * SIDE + x + width; ++i) set_arr_bit(out, i); + for (int i = (y + height - 1) * SIDE + x; i < (y + height - 1) * SIDE + x + width; ++i) + set_arr_bit(out, i); + for (int i = (y + 1) * SIDE + x; i < (y + height - 1) * SIDE + x; i += SIDE) + set_arr_bit(out, i); + for (int i = (y + 1) * SIDE + x + width - 1; i < (y + height - 1) * SIDE + x + width - 1; + i += SIDE) + set_arr_bit(out, i); + } else { + for (int i = y * SIDE + x; i < y * SIDE + x + width; ++i) clr_arr_bit(out, i); + for (int i = (y + height - 1) * SIDE + x; i < (y + height - 1) * SIDE + x + width; ++i) + clr_arr_bit(out, i); + for (int i = (y + 1) * SIDE + x; i < (y + height - 1) * SIDE + x; i += SIDE) + clr_arr_bit(out, i); + for (int i = (y + 1) * SIDE + x + width - 1; i < (y + height - 1) * SIDE + x + width - 1; + i += SIDE) + clr_arr_bit(out, i); + } +} + +template <int V> +void Qr<V>::reserve_patterns(uint8_t* out) { + draw_rect<true>(0, 6, SIDE, 1, out); + draw_rect<true>(6, 0, 1, SIDE, out); + + draw_rect<true>(0, 0, 9, 9, out); + draw_rect<true>(SIDE - 8, 0, 8, 9, out); + draw_rect<true>(0, SIDE - 8, 9, 8, out); + + for (int i = 0; i < N_ALIGN; ++i) { + for (int j = 0; j < N_ALIGN; ++j) { + if ((!i && !j) || (!i && j == N_ALIGN - 1) || (!j && i == N_ALIGN - 1)) continue; + draw_rect<true>(ALIGN_POS[V][i] - 2, ALIGN_POS[V][j] - 2, 5, 5, out); + } + } + + if (V >= 7) { + draw_rect<true>(SIDE - 11, 0, 3, 6, out); + draw_rect<true>(0, SIDE - 11, 6, 3, out); + } +} + +template <int V> +template <bool H> +int Qr<V>::rule_1_3_score() { + constexpr int y_max = H ? N_BITS : SIDE; + constexpr int x_max = H ? SIDE : N_BITS; + constexpr int y_step = H ? SIDE : 1; + constexpr int x_step = H ? 1 : SIDE; + + int res = 0; + + for (int y = 0; y < y_max; y += y_step) { + bool color = get_arr_bit(code, y); + int finder = color; + int cnt = 1; + for (int x = 1; x < x_max; x += x_step) { + if (get_arr_bit(code, y + x) == color) { + ++cnt; + if (cnt == 5) res += 3; + if (cnt > 5) ++res; + } else { + color = !color; + cnt = 1; + } + // Finder-like + finder = ((finder << 1) & 0x7ff) | color; + if (x >= x_step * 10) { + if (finder == 0x05d || finder == 0x5d0) res += 40; + } + } + } + return res; +} + +template <int V> +int Qr<V>::penalty_score() { + int res = 0; + + res += rule_1_3_score<true>(); + res += rule_1_3_score<false>(); + + for (int y = 0; y < N_BITS - SIDE; y += SIDE) { + for (int x = 0; x < SIDE - 1; ++x) { + bool c = get_arr_bit(code, y + x); + + if (c == get_arr_bit(code, y + x + 1) && c == get_arr_bit(code, y + x + SIDE) && + c == get_arr_bit(code, y + x + SIDE + 1)) + res += 3; + } + } + + int black = 0; + for (int y = 0; y < N_BITS; y += SIDE) { + for (int x = 0; x < SIDE; ++x) black += get_arr_bit(code, y + x); + } + res += abs((black * 100) / N_BITS - 50) / 5 * 10; + + return res; +} + +template <int V> +int Qr<V>::select_mask(Ecc ecc, uint8_t* patterns) { + unsigned min_score = -1; + unsigned score = 0; + uint8_t mask = 0; + + for (int i = 0; i < 8; ++i) { + add_format(ecc, i); + apply_mask(i, patterns); + score = penalty_score(); + if (score < min_score) { + mask = i; + min_score = score; + } + apply_mask(i, patterns); + } + return mask; +} + +template <int V> +void Qr<V>::apply_mask(int mask, uint8_t* patterns) { + for (int y = 0, dy = 0; y < SIDE; ++y, dy += SIDE) { + for (int x = 0; x < SIDE; ++x) { + int coord = dy + x; + + if (get_arr_bit(patterns, coord)) continue; + + bool keep = true; + + switch (mask) { + case 0: + keep = (x + y) & 1; + break; + case 1: + keep = y & 1; + break; + case 2: + keep = x % 3; + break; + case 3: + keep = (x + y) % 3; + break; + case 4: + keep = (y / 2 + x / 3) & 1; + break; + case 5: + keep = x * y % 2 + x * y % 3; + break; + case 6: + keep = (x * y % 2 + x * y % 3) & 1; + break; + case 7: + keep = ((x + y) % 2 + x * y % 3) & 1; + break; + } + + if (!keep) { + if (get_arr_bit(code, coord)) + clr_arr_bit(code, coord); + else + set_arr_bit(code, coord); + } + } + } +} + +/// @brief QR code encoder class. +class QrDelegate final { + public: + explicit QrDelegate() = default; + ~QrDelegate() = default; + + NE_COPY_DEFAULT(QrDelegate) + + /// @brief Draw method delegate. + template <Int32 V> + bool draw(Qr<V>& subject, Int32 x, Int32 y) noexcept { + return subject.draw(x, y); + } +}; +} // namespace qr + +namespace Kernel::Qr { +using namespace qr; +} // namespace Kernel::Qr + +#endif // QR_H
\ No newline at end of file diff --git a/dev/boot/BootKit/Shared/base.h b/dev/boot/BootKit/Shared/base.h index 88459ec3..c95db0cc 100644 --- a/dev/boot/BootKit/Shared/base.h +++ b/dev/boot/BootKit/Shared/base.h @@ -1,26 +1,24 @@ #ifndef UTL_BASE_H #define UTL_BASE_H -#include <stdint.h> -#include <stddef.h> #include <math.h> +#include <stddef.h> +#include <stdint.h> -namespace utl -{ +namespace utl { - /** - * @brief Helper to get number of elements in array. - * - * @tparam T Auto-deduced element type - * @tparam N Auto-deduced number of elements - * @return Array size - */ - template <class T, size_t N> - constexpr size_t countof(T (&)[N]) - { - return N; - } +/** + * @brief Helper to get number of elements in array. + * + * @tparam T Auto-deduced element type + * @tparam N Auto-deduced number of elements + * @return Array size + */ +template <class T, size_t N> +constexpr size_t countof(T (&)[N]) { + return N; +} -} // namespace utl +} // namespace utl #endif
\ No newline at end of file diff --git a/dev/boot/BootKit/Shared/bit.h b/dev/boot/BootKit/Shared/bit.h index fa0fab82..1ac29c89 100644 --- a/dev/boot/BootKit/Shared/bit.h +++ b/dev/boot/BootKit/Shared/bit.h @@ -3,245 +3,226 @@ #include <bit> -namespace utl -{ - - /** - * @brief Size of object in terms of bits. - * - * @tparam T Object type - * @return Number of bits - */ - template <class T> - constexpr auto bit_size() - { - return sizeof(T) * 8; - } - - /** - * @brief Integer with all bits set to 1. - * - * @tparam T Integer type - * @return All set integer - */ - template <class T> - constexpr T bit_full() - { - return T(-1); - } - - /** - * @brief Wrap around mask for power of two number of bits - * within given integer type. For example: - * [ bit_wrap<uint8_t> = 8 - 1 = 0b111 ] - * [ bit_wrap<uint16_t> = 16 - 1 = 0b1111 ] - * [ bit_wrap<uint32_t> = 32 - 1 = 0b11111 ] - * - * @tparam T Integer type - * @return Wrap around mask for number of bits - */ - template <class T> - constexpr T bit_wrap() - { - return bit_size<T>() - 1; - } - - /** - * @brief Number of bits to fit bit_wrap<T> result, in other words - * bit width of (sizeof(T) * 8 - 1). For example: - * [ bit_shft<uint8_t> = bit_width(0b111) = 3 ] - * [ bit_shft<uint16_t> = bit_width(0b1111) = 4 ] - * [ bit_shft<uint32_t> = bit_width(0b11111) = 5 ] - * - * @tparam T Integer type - * @return Number of bits to shift to divide by sizeof(T) * 8 - */ - template <class T> - constexpr auto bit_shft() - { - return std::bit_width(bit_wrap<T>()); - } - - /** - * @brief Round up division by number of bits within given integer type, - * which sizeof(T) * 8 is power of two. - * - * @tparam T Inetegr type - * @param x Dividend - * @return Quotient - */ - template <class T> - constexpr auto bit_ceil(auto x) - { - return (x + bit_wrap<T>()) >> bit_shft<T>(); - } - - /** - * @brief Count leading zeros. - * - * @param x Unsigned integer argument - * @return Number of leading zeros - */ - constexpr unsigned cntlz(auto x) - { - if constexpr (std::is_same_v<decltype(x), int>) - return std::countl_zero(unsigned(x)); - else - return std::countl_zero(x); - } - - /** - * @brief Count trailing zeros. - * - * @param x Unsigned integer argument - * @return Number of trailing zeros - */ - constexpr unsigned cnttz(auto x) - { - if constexpr (std::is_same_v<decltype(x), int>) - return std::countr_zero(unsigned(x)); - else - return std::countr_zero(x); - } - - /** - * @brief Get number of words (integers) required to store N bits. - * - * @tparam T Word integer type - * @param n Number of bits to store - * @return Number of words - */ - template <class T> - constexpr size_t words_in_bits(size_t n) - { - return (n >> bit_shft<T>()) + !!(n & bit_wrap<T>()); - } - - /** - * @brief Get number of bytes required to store N bits. - * - * @param n Number of bits to store - * @return Number of bytes - */ - constexpr size_t bytes_in_bits(size_t n) - { - return words_in_bits<uint8_t>(n); - } - - /** - * @brief Make integer with bit at given position. - * - * @tparam T Inetegr type - * @param n Bit position - * @return Integer with set bit - */ - template <class T = unsigned> - constexpr T bit(int n) - { - return T(1) << n; - } - - /** - * @brief Get n-th bit of an integer. - * - * @tparam T Integer type - * @param x Integer - * @param n Bit position from LSB - * @return true if set - */ - template <class T> - constexpr bool get_bit(T x, int n) - { - return (x >> n) & 1; - } - - /** - * @brief Set n-th bit of an integer. - * - * @tparam T Integer type - * @param x Integer - * @param n Bit position from LSB - */ - template <class T> - constexpr void set_bit(T& x, int n) - { - x |= 1 << n; - } - - /** - * @brief Clear n-th bit of an integer. - * - * @tparam T Integer type - * @param x Integer - * @param n Bit position from LSB - */ - template <class T> - constexpr void clr_bit(T& x, int n) - { - x &= ~(1 << n); - } - - /** - * @brief Get n-th bit in array of words (starting from LSB). - * - * @tparam T Word type - * @param p Array of words - * @param n Index of bit to get - * @return true if set - */ - template <class T> - constexpr bool get_arr_bit(const T* p, unsigned n) - { - return get_bit(p[n >> bit_shft<T>()], n & bit_wrap<T>()); - } - - /** - * @brief Set n-th bit in array of words (starting from LSB). - * - * @tparam T Word type - * @param p Array of words - * @param n Index of bit to set - */ - template <class T> - constexpr void set_arr_bit(T* p, unsigned n) - { - set_bit(p[n >> bit_shft<T>()], n & bit_wrap<T>()); - } - - /** - * @brief Clear n-th bit in array of words (starting from LSB). - * - * @tparam T Word type - * @param p Array of words - * @param n Index of bit to clear - */ - template <class T> - constexpr void clr_arr_bit(T* p, unsigned n) - { - clr_bit(p[n >> bit_shft<T>()], n & bit_wrap<T>()); - } - - /** - * @brief Shift bits left in array of integer elements from least significant bit - * and considering 0-th byte as the right most. - * uint16_t example: 0b10000000'11100001 ==> 0b00000001'11000010. - * - * @tparam T Integer type - * @tparam L Length of array - * @param x Array of integers, nullptr not acceptable! - * @param len Number of elements - */ - template <class T, size_t L> - constexpr void shift_left(T (&x)[L]) - { - for (int i = L - 1; i > 0; --i) - { - x[i] <<= 1; - x[i] |= x[i - 1] >> bit_wrap<T>(); - } - x[0] <<= 1; - } - -} // namespace utl +namespace utl { + +/** + * @brief Size of object in terms of bits. + * + * @tparam T Object type + * @return Number of bits + */ +template <class T> +constexpr auto bit_size() { + return sizeof(T) * 8; +} + +/** + * @brief Integer with all bits set to 1. + * + * @tparam T Integer type + * @return All set integer + */ +template <class T> +constexpr T bit_full() { + return T(-1); +} + +/** + * @brief Wrap around mask for power of two number of bits + * within given integer type. For example: + * [ bit_wrap<uint8_t> = 8 - 1 = 0b111 ] + * [ bit_wrap<uint16_t> = 16 - 1 = 0b1111 ] + * [ bit_wrap<uint32_t> = 32 - 1 = 0b11111 ] + * + * @tparam T Integer type + * @return Wrap around mask for number of bits + */ +template <class T> +constexpr T bit_wrap() { + return bit_size<T>() - 1; +} + +/** + * @brief Number of bits to fit bit_wrap<T> result, in other words + * bit width of (sizeof(T) * 8 - 1). For example: + * [ bit_shft<uint8_t> = bit_width(0b111) = 3 ] + * [ bit_shft<uint16_t> = bit_width(0b1111) = 4 ] + * [ bit_shft<uint32_t> = bit_width(0b11111) = 5 ] + * + * @tparam T Integer type + * @return Number of bits to shift to divide by sizeof(T) * 8 + */ +template <class T> +constexpr auto bit_shft() { + return std::bit_width(bit_wrap<T>()); +} + +/** + * @brief Round up division by number of bits within given integer type, + * which sizeof(T) * 8 is power of two. + * + * @tparam T Inetegr type + * @param x Dividend + * @return Quotient + */ +template <class T> +constexpr auto bit_ceil(auto x) { + return (x + bit_wrap<T>()) >> bit_shft<T>(); +} + +/** + * @brief Count leading zeros. + * + * @param x Unsigned integer argument + * @return Number of leading zeros + */ +constexpr unsigned cntlz(auto x) { + if constexpr (std::is_same_v<decltype(x), int>) + return std::countl_zero(unsigned(x)); + else + return std::countl_zero(x); +} + +/** + * @brief Count trailing zeros. + * + * @param x Unsigned integer argument + * @return Number of trailing zeros + */ +constexpr unsigned cnttz(auto x) { + if constexpr (std::is_same_v<decltype(x), int>) + return std::countr_zero(unsigned(x)); + else + return std::countr_zero(x); +} + +/** + * @brief Get number of words (integers) required to store N bits. + * + * @tparam T Word integer type + * @param n Number of bits to store + * @return Number of words + */ +template <class T> +constexpr size_t words_in_bits(size_t n) { + return (n >> bit_shft<T>()) + !!(n & bit_wrap<T>()); +} + +/** + * @brief Get number of bytes required to store N bits. + * + * @param n Number of bits to store + * @return Number of bytes + */ +constexpr size_t bytes_in_bits(size_t n) { + return words_in_bits<uint8_t>(n); +} + +/** + * @brief Make integer with bit at given position. + * + * @tparam T Inetegr type + * @param n Bit position + * @return Integer with set bit + */ +template <class T = unsigned> +constexpr T bit(int n) { + return T(1) << n; +} + +/** + * @brief Get n-th bit of an integer. + * + * @tparam T Integer type + * @param x Integer + * @param n Bit position from LSB + * @return true if set + */ +template <class T> +constexpr bool get_bit(T x, int n) { + return (x >> n) & 1; +} + +/** + * @brief Set n-th bit of an integer. + * + * @tparam T Integer type + * @param x Integer + * @param n Bit position from LSB + */ +template <class T> +constexpr void set_bit(T& x, int n) { + x |= 1 << n; +} + +/** + * @brief Clear n-th bit of an integer. + * + * @tparam T Integer type + * @param x Integer + * @param n Bit position from LSB + */ +template <class T> +constexpr void clr_bit(T& x, int n) { + x &= ~(1 << n); +} + +/** + * @brief Get n-th bit in array of words (starting from LSB). + * + * @tparam T Word type + * @param p Array of words + * @param n Index of bit to get + * @return true if set + */ +template <class T> +constexpr bool get_arr_bit(const T* p, unsigned n) { + return get_bit(p[n >> bit_shft<T>()], n & bit_wrap<T>()); +} + +/** + * @brief Set n-th bit in array of words (starting from LSB). + * + * @tparam T Word type + * @param p Array of words + * @param n Index of bit to set + */ +template <class T> +constexpr void set_arr_bit(T* p, unsigned n) { + set_bit(p[n >> bit_shft<T>()], n & bit_wrap<T>()); +} + +/** + * @brief Clear n-th bit in array of words (starting from LSB). + * + * @tparam T Word type + * @param p Array of words + * @param n Index of bit to clear + */ +template <class T> +constexpr void clr_arr_bit(T* p, unsigned n) { + clr_bit(p[n >> bit_shft<T>()], n & bit_wrap<T>()); +} + +/** + * @brief Shift bits left in array of integer elements from least significant bit + * and considering 0-th byte as the right most. + * uint16_t example: 0b10000000'11100001 ==> 0b00000001'11000010. + * + * @tparam T Integer type + * @tparam L Length of array + * @param x Array of integers, nullptr not acceptable! + * @param len Number of elements + */ +template <class T, size_t L> +constexpr void shift_left(T (&x)[L]) { + for (int i = L - 1; i > 0; --i) { + x[i] <<= 1; + x[i] |= x[i - 1] >> bit_wrap<T>(); + } + x[0] <<= 1; +} + +} // namespace utl #endif
\ No newline at end of file diff --git a/dev/boot/BootKit/Support.h b/dev/boot/BootKit/Support.h index 72aac293..6e1407c2 100644 --- a/dev/boot/BootKit/Support.h +++ b/dev/boot/BootKit/Support.h @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ @@ -13,7 +13,7 @@ #include <string.h> #endif -#define kLongMax ((long)(~0UL >> 1)) +#define kLongMax ((long) (~0UL >> 1)) #define kLongMin (~kLongMax) #ifdef __BOOTZ__ @@ -40,134 +40,104 @@ EXTERN_C int strcmp(const char* whatToCheck, const char* whatToCheckRight); #include <string.h> -#endif // __BOOTZ__ +#endif // __BOOTZ__ -#define SetMem(dst, c, sz) memset(dst, c, sz) +#define SetMem(dst, c, sz) memset(dst, c, sz) #define MoveMem(dst, src, sz) memcpy(dst, src, sz) #define CopyMem(dst, src, sz) memcpy(dst, src, sz) -#define StrLen(src) strlen(src) -#define StrCmp(dst, src) strcmp(dst, src) +#define StrLen(src) strlen(src) +#define StrCmp(dst, src) strcmp(dst, src) -inline int IsSpace(int c) -{ - return c == ' '; +inline int IsSpace(int c) { + return c == ' '; } -inline int StringNCompare(const char* destination, const char* source, long length) -{ - long err = 0; +inline int StringNCompare(const char* destination, const char* source, long length) { + long err = 0; - for (long i = 0UL; i < length; ++i) - { - if (source[i] != destination[i]) - ++err; - } + for (long i = 0UL; i < length; ++i) { + if (source[i] != destination[i]) ++err; + } - return err; + return err; } -inline long StringToLong(const char* nptr, char** endptr, int base) -{ - const char *p = nptr, *endp; - bool is_neg = 0, overflow = 0; - - /* Need unsigned so (-kLongMin) can fit in these: */ - unsigned long n = 0UL, cutoff; - int cutlim; - - if (base < 0 || base == 1 || base > 36) - { - return 0L; - } - - endp = nptr; - - while (IsSpace(*p)) - p++; - - if (*p == '+') - { - p++; - } - else if (*p == '-') - { - is_neg = 1, p++; - } - if (*p == '0') - { - p++; - /* For strtol(" 0xZ", &endptr, 16), endptr should point to 'x'; - * pointing to ' ' or '0' is non-compliant. - * (Many implementations do this wrong.) */ - endp = p; - if (base == 16 && (*p == 'X' || *p == 'x')) - { - p++; - } - else if (base == 2 && (*p == 'B' || *p == 'b')) - { - /* C23 standard supports "0B" and "0b" prefixes. */ - p++; - } - else if (base == 0) - { - if (*p == 'X' || *p == 'x') - { - base = 16, p++; - } - else if (*p == 'B' || *p == 'b') - { - base = 2, p++; - } - else - { - base = 8; - } - } - } - else if (base == 0) - { - base = 10; - } - - cutoff = (is_neg) ? -(kLongMin / base) : kLongMax / base; - cutlim = (is_neg) ? -(kLongMin % base) : kLongMax % base; - - while (1) - { - int c; - if (*p >= 'A') - c = ((*p - 'A') & (~('a' ^ 'A'))) + 10; - else if (*p <= '9') - c = *p - '0'; - else - break; - if (c < 0 || c >= base) - break; - endp = ++p; - if (overflow) - { - /* endptr should go forward and point to the non-digit character - * (of the given base); required by ANSI standard. */ - if (endptr) - continue; - break; - } - if (n > cutoff || (n == cutoff && c > cutlim)) - { - overflow = 1; - continue; - } - n = n * base + c; - } - - if (endptr) - *endptr = (char*)endp; - - if (overflow) - { - return ((is_neg) ? kLongMin : kLongMax); - } - - return (long)((is_neg) ? -n : n); +inline long StringToLong(const char* nptr, char** endptr, int base) { + const char *p = nptr, *endp; + bool is_neg = 0, overflow = 0; + + /* Need unsigned so (-kLongMin) can fit in these: */ + unsigned long n = 0UL, cutoff; + int cutlim; + + if (base < 0 || base == 1 || base > 36) { + return 0L; + } + + endp = nptr; + + while (IsSpace(*p)) p++; + + if (*p == '+') { + p++; + } else if (*p == '-') { + is_neg = 1, p++; + } + if (*p == '0') { + p++; + /* For strtol(" 0xZ", &endptr, 16), endptr should point to 'x'; + * pointing to ' ' or '0' is non-compliant. + * (Many implementations do this wrong.) */ + endp = p; + if (base == 16 && (*p == 'X' || *p == 'x')) { + p++; + } else if (base == 2 && (*p == 'B' || *p == 'b')) { + /* C23 standard supports "0B" and "0b" prefixes. */ + p++; + } else if (base == 0) { + if (*p == 'X' || *p == 'x') { + base = 16, p++; + } else if (*p == 'B' || *p == 'b') { + base = 2, p++; + } else { + base = 8; + } + } + } else if (base == 0) { + base = 10; + } + + cutoff = (is_neg) ? -(kLongMin / base) : kLongMax / base; + cutlim = (is_neg) ? -(kLongMin % base) : kLongMax % base; + + while (1) { + int c; + if (*p >= 'A') + c = ((*p - 'A') & (~('a' ^ 'A'))) + 10; + else if (*p <= '9') + c = *p - '0'; + else + break; + if (c < 0 || c >= base) break; + endp = ++p; + if (overflow) { + /* endptr should go forward and point to the non-digit character + * (of the given base); required by ANSI standard. */ + if (endptr) continue; + break; + } + if (n > cutoff || (n == cutoff && c > cutlim)) { + overflow = 1; + continue; + } + n = n * base + c; + } + + if (endptr) *endptr = (char*) endp; + + if (overflow) { + return ((is_neg) ? kLongMin : kLongMax); + } + + return (long) ((is_neg) ? -n : n); } diff --git a/dev/boot/modules/BootNet/BootNet.cc b/dev/boot/modules/BootNet/BootNet.cc index 3e025949..840aabd5 100644 --- a/dev/boot/modules/BootNet/BootNet.cc +++ b/dev/boot/modules/BootNet/BootNet.cc @@ -7,117 +7,110 @@ * ======================================================== */ -#include <FirmwareKit/EFI/API.h> -#include <modules/BootNet/BootNet.h> #include <BootKit/BootKit.h> #include <BootKit/BootThread.h> +#include <FirmwareKit/EFI/API.h> +#include <modules/BootNet/BootNet.h> -STATIC EfiGUID kEfiSimpleProtoGUID = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; -STATIC EFI_SIMPLE_NETWORK_PROTOCOL* kEfiProtocol = nullptr; +STATIC EfiGUID kEfiSimpleProtoGUID = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; +STATIC EFI_SIMPLE_NETWORK_PROTOCOL* kEfiProtocol = nullptr; -STATIC Void bootnet_read_ip_packet(BOOTNET_INTERNET_HEADER inet, BOOTNET_INTERNET_HEADER** inet_out); +STATIC Void bootnet_read_ip_packet(BOOTNET_INTERNET_HEADER inet, + BOOTNET_INTERNET_HEADER** inet_out); -EXTERN_C Int32 BootNetModuleMain(Kernel::HEL::BootInfoHeader* handover) -{ - fw_init_efi((EfiSystemTable*)handover->f_FirmwareCustomTables[1]); +EXTERN_C Int32 BootNetModuleMain(Kernel::HEL::BootInfoHeader* handover) { + fw_init_efi((EfiSystemTable*) handover->f_FirmwareCustomTables[1]); - Boot::BootTextWriter writer; + Boot::BootTextWriter writer; - writer.Write("BootNet: Init BootNet...\r"); + writer.Write("BootNet: Init BootNet...\r"); - if (BS->LocateProtocol(&kEfiSimpleProtoGUID, nullptr, (VoidPtr*)&kEfiProtocol) != kEfiOk) - { - writer.Write("BootNet: Not supported by firmware.\r"); - return kEfiFail; - } + if (BS->LocateProtocol(&kEfiSimpleProtoGUID, nullptr, (VoidPtr*) &kEfiProtocol) != kEfiOk) { + writer.Write("BootNet: Not supported by firmware.\r"); + return kEfiFail; + } - BOOTNET_INTERNET_HEADER inet{}; - BOOTNET_INTERNET_HEADER* inet_out = nullptr; + BOOTNET_INTERNET_HEADER inet{}; + BOOTNET_INTERNET_HEADER* inet_out = nullptr; - SetMem(&inet, 0, sizeof(BOOTNET_INTERNET_HEADER)); + SetMem(&inet, 0, sizeof(BOOTNET_INTERNET_HEADER)); - writer.Write("BootNet: Downloading kernel...\r"); + writer.Write("BootNet: Downloading kernel...\r"); - bootnet_read_ip_packet(inet, &inet_out); + bootnet_read_ip_packet(inet, &inet_out); - if (inet_out->Length < 1) - { - writer.Write("BootNet: No executable attached to the packet, aborting.\r"); - return kEfiFail; - } + if (inet_out->Length < 1) { + writer.Write("BootNet: No executable attached to the packet, aborting.\r"); + return kEfiFail; + } - if (!inet_out->ImpliesProgram) - { - Boot::BootThread thread(inet_out->Data); + if (!inet_out->ImpliesProgram) { + Boot::BootThread thread(inet_out->Data); - if (thread.IsValid()) - { - writer.Write("BootNet: Running kernel...\r"); - return thread.Start(handover, YES); - } + if (thread.IsValid()) { + writer.Write("BootNet: Running kernel...\r"); + return thread.Start(handover, YES); + } - return kEfiFail; - } - else - { - constexpr auto kROMSize = 0x200; + return kEfiFail; + } else { + constexpr auto kROMSize = 0x200; - if (inet_out->Length > kROMSize) - { - writer.Write("BootNet: Not within 512K.\r"); - return kEfiFail; - } + if (inet_out->Length > kROMSize) { + writer.Write("BootNet: Not within 512K.\r"); + return kEfiFail; + } - writer.Write("BootNet: Programming the flash...\r"); + writer.Write("BootNet: Programming the flash...\r"); - /// TODO: Program new firmware to EEPROM (if crc and size matches) + /// TODO: Program new firmware to EEPROM (if crc and size matches) - const ATTRIBUTE(unused) UIntPtr kEEPROMStartAddress = 0; - const ATTRIBUTE(unused) UInt16 kEEPROMSize = inet_out->Length; + const ATTRIBUTE(unused) UIntPtr kEEPROMStartAddress = 0; + const ATTRIBUTE(unused) UInt16 kEEPROMSize = inet_out->Length; - return kEfiFail; - } + return kEfiFail; + } - return kEfiFail; + return kEfiFail; } -STATIC Void bootnet_read_ip_packet(BOOTNET_INTERNET_HEADER inet, BOOTNET_INTERNET_HEADER** inet_out) -{ - NE_UNUSED(inet); +STATIC Void bootnet_read_ip_packet(BOOTNET_INTERNET_HEADER inet, + BOOTNET_INTERNET_HEADER** inet_out) { + NE_UNUSED(inet); - kEfiProtocol->Start(kEfiProtocol); + kEfiProtocol->Start(kEfiProtocol); - UInt32 size_inet = sizeof(inet); + UInt32 size_inet = sizeof(inet); - /// Connect to the local BootNet server. + /// Connect to the local BootNet server. - /// And receive the handshake packet. - if (kEfiProtocol->Receive(kEfiProtocol, &size_inet, (UInt32*)&inet.Length, (VoidPtr)&inet, nullptr, nullptr, nullptr) == kEfiOk) - { - BOOTNET_INTERNET_HEADER* out = nullptr; + /// And receive the handshake packet. + if (kEfiProtocol->Receive(kEfiProtocol, &size_inet, (UInt32*) &inet.Length, (VoidPtr) &inet, + nullptr, nullptr, nullptr) == kEfiOk) { + BOOTNET_INTERNET_HEADER* out = nullptr; - BS->AllocatePool(EfiLoaderData, sizeof(BOOTNET_INTERNET_HEADER) + inet.Length, (VoidPtr*)&out); + BS->AllocatePool(EfiLoaderData, sizeof(BOOTNET_INTERNET_HEADER) + inet.Length, (VoidPtr*) &out); - if (out == nullptr) - { - kEfiProtocol->Stop(kEfiProtocol); - kEfiProtocol->Shutdown(kEfiProtocol); - return; - } + if (out == nullptr) { + kEfiProtocol->Stop(kEfiProtocol); + kEfiProtocol->Shutdown(kEfiProtocol); + return; + } - SetMem(out, 0, sizeof(BOOTNET_INTERNET_HEADER)); - SetMem(out->Data, 0, inet.Length); + SetMem(out, 0, sizeof(BOOTNET_INTERNET_HEADER)); + SetMem(out->Data, 0, inet.Length); - size_inet = sizeof(BOOTNET_INTERNET_HEADER); + size_inet = sizeof(BOOTNET_INTERNET_HEADER); - auto full_size = size_inet + inet.Length; + auto full_size = size_inet + inet.Length; - /// Ask for it again since we know the full_size variable now. - kEfiProtocol->Receive(kEfiProtocol, &size_inet, (UInt32*)&full_size, (VoidPtr)out, nullptr, nullptr, nullptr); + /// Ask for it again since we know the full_size variable now. + kEfiProtocol->Receive(kEfiProtocol, &size_inet, (UInt32*) &full_size, (VoidPtr) out, nullptr, + nullptr, nullptr); - *inet_out = out; - } + *inet_out = out; + } - kEfiProtocol->Stop(kEfiProtocol); - kEfiProtocol->Shutdown(kEfiProtocol); + kEfiProtocol->Stop(kEfiProtocol); + kEfiProtocol->Shutdown(kEfiProtocol); }
\ No newline at end of file diff --git a/dev/boot/modules/SysChk/SysChk.cc b/dev/boot/modules/SysChk/SysChk.cc index 032c031d..a3697bb1 100644 --- a/dev/boot/modules/SysChk/SysChk.cc +++ b/dev/boot/modules/SysChk/SysChk.cc @@ -8,8 +8,7 @@ */ #include <BootKit/BootKit.h> -#include <modules/CoreGfx/CoreGfx.h> -#include <modules/CoreGfx/TextGfx.h> +#include <BootKit/BootThread.h> #include <FirmwareKit/EFI.h> #include <FirmwareKit/EFI/API.h> #include <FirmwareKit/Handover.h> @@ -18,28 +17,26 @@ #include <KernelKit/PEF.h> #include <NewKit/Macros.h> #include <NewKit/Ref.h> -#include <BootKit/BootThread.h> #include <modules/CoreGfx/CoreGfx.h> +#include <modules/CoreGfx/TextGfx.h> // Makes the compiler shut up. #ifndef kMachineModel #define kMachineModel "OS" -#endif // !kMachineModel +#endif // !kMachineModel -EXTERN_C Int32 SysChkModuleMain(Kernel::HEL::BootInfoHeader* handover) -{ +EXTERN_C Int32 SysChkModuleMain(Kernel::HEL::BootInfoHeader* handover) { #if defined(__ATA_PIO__) - fw_init_efi((EfiSystemTable*)handover->f_FirmwareCustomTables[1]); + fw_init_efi((EfiSystemTable*) handover->f_FirmwareCustomTables[1]); - Boot::BDiskFormatFactory<BootDeviceATA> partition_factory; + Boot::BDiskFormatFactory<BootDeviceATA> partition_factory; - if (partition_factory.IsPartitionValid()) - return kEfiOk; + if (partition_factory.IsPartitionValid()) return kEfiOk; - return partition_factory.Format(kMachineModel) == YES; + return partition_factory.Format(kMachineModel) == YES; #else - NE_UNUSED(handover); + NE_UNUSED(handover); - return kEfiOk; + return kEfiOk; #endif } diff --git a/dev/boot/src/BootFileReader.cc b/dev/boot/src/BootFileReader.cc index 1236b7f0..32060bd7 100644 --- a/dev/boot/src/BootFileReader.cc +++ b/dev/boot/src/BootFileReader.cc @@ -1,18 +1,18 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. - File: FileReader.cc - Purpose: New Boot FileReader, - Read complete file and store it in a buffer. + File: FileReader.cc + Purpose: New Boot FileReader, + Read complete file and store it in a buffer. ------------------------------------------- */ +#include <BootKit/BootKit.h> #include <BootKit/Platform.h> #include <BootKit/Protocol.h> -#include <BootKit/BootKit.h> -#include <FirmwareKit/Handover.h> #include <FirmwareKit/EFI/API.h> +#include <FirmwareKit/Handover.h> #include <modules/CoreGfx/TextGfx.h> /// @file BootFileReader @@ -29,178 +29,149 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// /*** - @brief File Reader constructor. + @brief File Reader constructor. */ -Boot::BootFileReader::BootFileReader(const CharacterTypeUTF16* path, - EfiHandlePtr ImageHandle) -{ - if (path != nullptr) - { - SizeT index = 0UL; - for (; path[index] != L'\0'; ++index) - { - mPath[index] = path[index]; - } - - mPath[index] = 0; - } - - /// Load protocols with their GUIDs. - - EfiGUID guidEfp = EfiGUID(EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID); - - EfiSimpleFilesystemProtocol* efp = nullptr; - - EfiLoadImageProtocol* img = nullptr; - EfiGUID guidImg = EfiGUID(EFI_LOADED_IMAGE_PROTOCOL_GUID); - - if (BS->HandleProtocol(ImageHandle, &guidImg, (void**)&img) != kEfiOk) - { - mWriter.Write(L"BootZ: Handle-Protocol: No-Such-Protocol").Write(L"\r"); - this->mErrorCode = kNotSupported; - } - - if (BS->HandleProtocol(img->DeviceHandle, &guidEfp, (void**)&efp) != kEfiOk) - { - mWriter.Write(L"BootZ: Handle-Protocol: No-Such-Protocol").Write(L"\r"); - this->mErrorCode = kNotSupported; - return; - } - - /// Start doing disk I/O - - if (efp->OpenVolume(efp, &mRootFs) != kEfiOk) - { - mWriter.Write(L"BootZ: Fetch-Protocol: No-Such-Volume").Write(L"\r"); - this->mErrorCode = kNotSupported; - return; - } - - EfiFileProtocol* fileFs = nullptr; - - if (mRootFs->Open(mRootFs, &fileFs, mPath, kEFIFileRead, kEFIReadOnly) != - kEfiOk) - { - mWriter.Write(L"BootZ: Fetch-Protocol: No-Such-Path: ") - .Write(mPath) - .Write(L"\r"); - this->mErrorCode = kNotSupported; - - fb_render_string("BootZ: PLEASE RECOVER YOUR MINKRNL INSTALL.", 40, 10, RGB(0xFF, 0xFF, 0xFF)); - - mRootFs->Close(mRootFs); - - return; - } - - mSizeFile = 0; - mFile = fileFs; - mErrorCode = kOperationOkay; +Boot::BootFileReader::BootFileReader(const CharacterTypeUTF16* path, EfiHandlePtr ImageHandle) { + if (path != nullptr) { + SizeT index = 0UL; + for (; path[index] != L'\0'; ++index) { + mPath[index] = path[index]; + } + + mPath[index] = 0; + } + + /// Load protocols with their GUIDs. + + EfiGUID guidEfp = EfiGUID(EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID); + + EfiSimpleFilesystemProtocol* efp = nullptr; + + EfiLoadImageProtocol* img = nullptr; + EfiGUID guidImg = EfiGUID(EFI_LOADED_IMAGE_PROTOCOL_GUID); + + if (BS->HandleProtocol(ImageHandle, &guidImg, (void**) &img) != kEfiOk) { + mWriter.Write(L"BootZ: Handle-Protocol: No-Such-Protocol").Write(L"\r"); + this->mErrorCode = kNotSupported; + } + + if (BS->HandleProtocol(img->DeviceHandle, &guidEfp, (void**) &efp) != kEfiOk) { + mWriter.Write(L"BootZ: Handle-Protocol: No-Such-Protocol").Write(L"\r"); + this->mErrorCode = kNotSupported; + return; + } + + /// Start doing disk I/O + + if (efp->OpenVolume(efp, &mRootFs) != kEfiOk) { + mWriter.Write(L"BootZ: Fetch-Protocol: No-Such-Volume").Write(L"\r"); + this->mErrorCode = kNotSupported; + return; + } + + EfiFileProtocol* fileFs = nullptr; + + if (mRootFs->Open(mRootFs, &fileFs, mPath, kEFIFileRead, kEFIReadOnly) != kEfiOk) { + mWriter.Write(L"BootZ: Fetch-Protocol: No-Such-Path: ").Write(mPath).Write(L"\r"); + this->mErrorCode = kNotSupported; + + fb_render_string("BootZ: PLEASE RECOVER YOUR MINKRNL INSTALL.", 40, 10, RGB(0xFF, 0xFF, 0xFF)); + + mRootFs->Close(mRootFs); + + return; + } + + mSizeFile = 0; + mFile = fileFs; + mErrorCode = kOperationOkay; } -Boot::BootFileReader::~BootFileReader() -{ - if (this->mFile) - { - this->mFile->Close(this->mFile); - this->mFile = nullptr; - } - - if (this->mRootFs) - { - this->mRootFs->Close(this->mRootFs); - this->mRootFs = nullptr; - } - - if (this->mBlob) - { - BS->FreePool(this->mBlob); - this->mBlob = nullptr; - } - - BSetMem(this->mPath, 0, kPathLen); +Boot::BootFileReader::~BootFileReader() { + if (this->mFile) { + this->mFile->Close(this->mFile); + this->mFile = nullptr; + } + + if (this->mRootFs) { + this->mRootFs->Close(this->mRootFs); + this->mRootFs = nullptr; + } + + if (this->mBlob) { + BS->FreePool(this->mBlob); + this->mBlob = nullptr; + } + + BSetMem(this->mPath, 0, kPathLen); } /** - @brief Reads all of the file into a buffer. - @param **readUntil** size of file - @param **chunkToRead** chunk to read each time. + @brief Reads all of the file into a buffer. + @param **readUntil** size of file + @param **chunkToRead** chunk to read each time. */ -Void Boot::BootFileReader::ReadAll(SizeT readUntil, SizeT chunkToRead, UIntPtr out_address) -{ - UInt32 szInfo = sizeof(EfiFileInfo); - - EfiFileInfo newPtrInfo{}; - - EfiGUID kFileInfoGUID = EFI_FILE_INFO_GUID; - - if (mFile->GetInfo(mFile, &kFileInfoGUID, &szInfo, &newPtrInfo) == kEfiOk) - { - readUntil = newPtrInfo.FileSize; - mWriter.Write(L"BootZ: File size: ").Write(readUntil).Write("\r"); - } - - if (readUntil == 0) - { - mErrorCode = kNotSupported; - return; - } - - if (mBlob == nullptr) - { - if (!out_address) - { - if (auto err = BS->AllocatePool(EfiLoaderCode, readUntil, (VoidPtr*)&mBlob) != - kEfiOk) - { - mWriter.Write(L"*** error: ").Write(err).Write(L" ***\r"); - Boot::ThrowError(L"OutOfMemory", L"Out of memory."); - } - } - else - { - mBlob = (VoidPtr)out_address; - } - } - - mWriter.Write(L"*** Bytes to read: ").Write(readUntil).Write(L" ***\r"); - - UInt64 bufSize = chunkToRead; - UInt64 szCnt = 0UL; - - while (szCnt < readUntil) - { - auto res = mFile->Read(mFile, &bufSize, (VoidPtr)(&((Char*)mBlob)[szCnt])); - - szCnt += bufSize; - - if (res == kBufferTooSmall) - { - bufSize = chunkToRead; - } - } - - mSizeFile = szCnt; - mErrorCode = kOperationOkay; +Void Boot::BootFileReader::ReadAll(SizeT readUntil, SizeT chunkToRead, UIntPtr out_address) { + UInt32 szInfo = sizeof(EfiFileInfo); + + EfiFileInfo newPtrInfo{}; + + EfiGUID kFileInfoGUID = EFI_FILE_INFO_GUID; + + if (mFile->GetInfo(mFile, &kFileInfoGUID, &szInfo, &newPtrInfo) == kEfiOk) { + readUntil = newPtrInfo.FileSize; + mWriter.Write(L"BootZ: File size: ").Write(readUntil).Write("\r"); + } + + if (readUntil == 0) { + mErrorCode = kNotSupported; + return; + } + + if (mBlob == nullptr) { + if (!out_address) { + if (auto err = BS->AllocatePool(EfiLoaderCode, readUntil, (VoidPtr*) &mBlob) != kEfiOk) { + mWriter.Write(L"*** error: ").Write(err).Write(L" ***\r"); + Boot::ThrowError(L"OutOfMemory", L"Out of memory."); + } + } else { + mBlob = (VoidPtr) out_address; + } + } + + mWriter.Write(L"*** Bytes to read: ").Write(readUntil).Write(L" ***\r"); + + UInt64 bufSize = chunkToRead; + UInt64 szCnt = 0UL; + + while (szCnt < readUntil) { + auto res = mFile->Read(mFile, &bufSize, (VoidPtr) (&((Char*) mBlob)[szCnt])); + + szCnt += bufSize; + + if (res == kBufferTooSmall) { + bufSize = chunkToRead; + } + } + + mSizeFile = szCnt; + mErrorCode = kOperationOkay; } /// @brief error code getter. /// @return the error code. -Int32& Boot::BootFileReader::Error() -{ - return mErrorCode; +Int32& Boot::BootFileReader::Error() { + return mErrorCode; } /// @brief blob getter. /// @return the blob. -VoidPtr Boot::BootFileReader::Blob() -{ - return mBlob; +VoidPtr Boot::BootFileReader::Blob() { + return mBlob; } /// @breif Size getter. /// @return the size of the file. -UInt64& Boot::BootFileReader::Size() -{ - return mSizeFile; +UInt64& Boot::BootFileReader::Size() { + return mSizeFile; } diff --git a/dev/boot/src/BootString.cc b/dev/boot/src/BootString.cc index 7efa5bca..8762a151 100644 --- a/dev/boot/src/BootString.cc +++ b/dev/boot/src/BootString.cc @@ -1,92 +1,81 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. - File: BootString.cc - Purpose: BootZ string library + File: BootString.cc + Purpose: BootZ string library - Revision History: + Revision History: ------------------------------------------- */ +#include <BootKit/BootKit.h> #include <BootKit/Platform.h> #include <BootKit/Protocol.h> -#include <BootKit/BootKit.h> /// BUGS: 0 ///////////////////////////////////////////////////////////////////////////////////////////////////////// -Kernel::SizeT Boot::BCopyMem(CharacterTypeUTF16* dest, CharacterTypeUTF16* src, const Kernel::SizeT len) -{ - if (!dest || !src) - return 0; +Kernel::SizeT Boot::BCopyMem(CharacterTypeUTF16* dest, CharacterTypeUTF16* src, + const Kernel::SizeT len) { + if (!dest || !src) return 0; - SizeT index = 0UL; - for (; index < len; ++index) - { - dest[index] = src[index]; - } + SizeT index = 0UL; + for (; index < len; ++index) { + dest[index] = src[index]; + } - return index; + return index; } -Kernel::SizeT Boot::BStrLen(const CharacterTypeUTF16* ptr) -{ - if (!ptr) - return 0; +Kernel::SizeT Boot::BStrLen(const CharacterTypeUTF16* ptr) { + if (!ptr) return 0; - Kernel::SizeT cnt = 0; + Kernel::SizeT cnt = 0; - while (*ptr != (CharacterTypeUTF16)0) - { - ++ptr; - ++cnt; - } + while (*ptr != (CharacterTypeUTF16) 0) { + ++ptr; + ++cnt; + } - return cnt; + return cnt; } -Kernel::SizeT Boot::BSetMem(CharacterTypeUTF16* src, const CharacterTypeUTF16 byte, const Kernel::SizeT len) -{ - if (!src) - return 0; +Kernel::SizeT Boot::BSetMem(CharacterTypeUTF16* src, const CharacterTypeUTF16 byte, + const Kernel::SizeT len) { + if (!src) return 0; - Kernel::SizeT cnt = 0UL; + Kernel::SizeT cnt = 0UL; - while (*src != 0) - { - if (cnt > len) - break; + while (*src != 0) { + if (cnt > len) break; - *src = byte; - ++src; + *src = byte; + ++src; - ++cnt; - } + ++cnt; + } - return cnt; + return cnt; } -Kernel::SizeT Boot::BSetMem(CharacterTypeUTF8* src, const CharacterTypeUTF8 byte, const Kernel::SizeT len) -{ - if (!src) - return 0; +Kernel::SizeT Boot::BSetMem(CharacterTypeUTF8* src, const CharacterTypeUTF8 byte, + const Kernel::SizeT len) { + if (!src) return 0; - Kernel::SizeT cnt = 0UL; + Kernel::SizeT cnt = 0UL; - while (*src != 0) - { - if (cnt > len) - break; + while (*src != 0) { + if (cnt > len) break; - *src = byte; - ++src; + *src = byte; + ++src; - ++cnt; - } + ++cnt; + } - return cnt; + return cnt; } diff --git a/dev/boot/src/BootSupport.cc b/dev/boot/src/BootSupport.cc index ade8ed01..ce824e0f 100644 --- a/dev/boot/src/BootSupport.cc +++ b/dev/boot/src/BootSupport.cc @@ -1,14 +1,14 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ #include <BootKit/BootKit.h> +#include <BootKit/Support.h> #include <FirmwareKit/EFI/API.h> #include <FirmwareKit/EFI/EFI.h> #include <FirmwareKit/Handover.h> -#include <BootKit/Support.h> #include <KernelKit/MSDOS.h> #include <KernelKit/PE.h> @@ -18,62 +18,51 @@ /// @param dst destination pointer. /// @param byte value to fill in. /// @param len length of of src. -EXTERN_C VoidPtr memset(void* dst, int byte, long long unsigned int len) -{ - for (size_t i = 0UL; i < len; ++i) - { - ((int*)dst)[i] = byte; - } - - return dst; +EXTERN_C VoidPtr memset(void* dst, int byte, long long unsigned int len) { + for (size_t i = 0UL; i < len; ++i) { + ((int*) dst)[i] = byte; + } + + return dst; } /// @brief memcpy definition in C++. /// @param dst destination pointer. /// @param src source pointer. /// @param len length of of src. -EXTERN_C VoidPtr memcpy(void* dst, const void* src, long long unsigned int len) -{ - for (size_t i = 0UL; i < len; ++i) - { - ((int*)dst)[i] = ((int*)src)[i]; - } - - return dst; +EXTERN_C VoidPtr memcpy(void* dst, const void* src, long long unsigned int len) { + for (size_t i = 0UL; i < len; ++i) { + ((int*) dst)[i] = ((int*) src)[i]; + } + + return dst; } /// @brief strlen definition in C++. -EXTERN_C size_t strlen(const char* whatToCheck) -{ - SizeT len = 0; +EXTERN_C size_t strlen(const char* whatToCheck) { + SizeT len = 0; - while (whatToCheck[len] != 0) - { - ++len; - } + while (whatToCheck[len] != 0) { + ++len; + } - return len; + return len; } /// @brief strcmp definition in C++. -EXTERN_C int strcmp(const char* whatToCheck, const char* whatToCheckRight) -{ - SizeT len = 0; +EXTERN_C int strcmp(const char* whatToCheck, const char* whatToCheckRight) { + SizeT len = 0; - while (whatToCheck[len] == whatToCheckRight[len]) - { - if (whatToCheck[len] == 0) - return 0; + while (whatToCheck[len] == whatToCheckRight[len]) { + if (whatToCheck[len] == 0) return 0; - ++len; - } + ++len; + } - return len; + return len; } /// @brief something specific to the Microsoft's ABI, When the stack grows too big. -EXTERN_C void ___chkstk_ms(void) -{ -} +EXTERN_C void ___chkstk_ms(void) {} #endif diff --git a/dev/boot/src/BootTextWriter.cc b/dev/boot/src/BootTextWriter.cc index 95e248a2..5e826c6d 100644 --- a/dev/boot/src/BootTextWriter.cc +++ b/dev/boot/src/BootTextWriter.cc @@ -1,20 +1,20 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. - File: BootTextWriter.cc - Purpose: BootZ string library + File: BootTextWriter.cc + Purpose: BootZ string library - Revision History: + Revision History: ------------------------------------------- */ -#include <FirmwareKit/EFI/API.h> +#include <BootKit/BootKit.h> #include <BootKit/Platform.h> #include <BootKit/Protocol.h> -#include <BootKit/BootKit.h> +#include <FirmwareKit/EFI/API.h> ///////////////////////////////////////////////////////////////////////////////////////////////////////// /// BUGS: 0 /// @@ -23,147 +23,123 @@ /** @brief puts wrapper over EFI ConOut. */ -Boot::BootTextWriter& Boot::BootTextWriter::Write(const CharacterTypeUTF16* str) -{ +Boot::BootTextWriter& Boot::BootTextWriter::Write(const CharacterTypeUTF16* str) { #ifdef __DEBUG__ - if (!str || *str == 0) - return *this; - - CharacterTypeUTF16 strTmp[2]; - strTmp[1] = 0; - - for (size_t i = 0; str[i] != 0; i++) - { - if (str[i] == '\r') - { - strTmp[0] = str[i]; - ST->ConOut->OutputString(ST->ConOut, strTmp); - - strTmp[0] = '\n'; - ST->ConOut->OutputString(ST->ConOut, strTmp); - } - else - { - strTmp[0] = str[i]; - ST->ConOut->OutputString(ST->ConOut, strTmp); - } - } -#endif // ifdef __DEBUG__ - - return *this; + if (!str || *str == 0) return *this; + + CharacterTypeUTF16 strTmp[2]; + strTmp[1] = 0; + + for (size_t i = 0; str[i] != 0; i++) { + if (str[i] == '\r') { + strTmp[0] = str[i]; + ST->ConOut->OutputString(ST->ConOut, strTmp); + + strTmp[0] = '\n'; + ST->ConOut->OutputString(ST->ConOut, strTmp); + } else { + strTmp[0] = str[i]; + ST->ConOut->OutputString(ST->ConOut, strTmp); + } + } +#endif // ifdef __DEBUG__ + + return *this; } /// @brief UTF-8 equivalent of Write (UTF-16). /// @param str the input string. -Boot::BootTextWriter& Boot::BootTextWriter::Write(const Char* str) -{ +Boot::BootTextWriter& Boot::BootTextWriter::Write(const Char* str) { #ifdef __DEBUG__ - if (!str || *str == 0) - return *this; - - CharacterTypeUTF16 strTmp[2]; - strTmp[1] = 0; - - for (size_t i = 0; str[i] != 0; i++) - { - if (str[i] == '\r') - { - strTmp[0] = str[i]; - ST->ConOut->OutputString(ST->ConOut, strTmp); - - strTmp[0] = '\n'; - ST->ConOut->OutputString(ST->ConOut, strTmp); - } - else - { - strTmp[0] = str[i]; - ST->ConOut->OutputString(ST->ConOut, strTmp); - } - } -#endif // ifdef __DEBUG__ - - return *this; + if (!str || *str == 0) return *this; + + CharacterTypeUTF16 strTmp[2]; + strTmp[1] = 0; + + for (size_t i = 0; str[i] != 0; i++) { + if (str[i] == '\r') { + strTmp[0] = str[i]; + ST->ConOut->OutputString(ST->ConOut, strTmp); + + strTmp[0] = '\n'; + ST->ConOut->OutputString(ST->ConOut, strTmp); + } else { + strTmp[0] = str[i]; + ST->ConOut->OutputString(ST->ConOut, strTmp); + } + } +#endif // ifdef __DEBUG__ + + return *this; } -Boot::BootTextWriter& Boot::BootTextWriter::Write(const UChar* str) -{ +Boot::BootTextWriter& Boot::BootTextWriter::Write(const UChar* str) { #ifdef __DEBUG__ - if (!str || *str == 0) - return *this; - - CharacterTypeUTF16 strTmp[2]; - strTmp[1] = 0; - - for (size_t i = 0; str[i] != 0; i++) - { - if (str[i] == '\r') - { - strTmp[0] = str[i]; - ST->ConOut->OutputString(ST->ConOut, strTmp); - - strTmp[0] = '\n'; - ST->ConOut->OutputString(ST->ConOut, strTmp); - } - else - { - strTmp[0] = str[i]; - ST->ConOut->OutputString(ST->ConOut, strTmp); - } - } -#endif // ifdef __DEBUG__ - - return *this; + if (!str || *str == 0) return *this; + + CharacterTypeUTF16 strTmp[2]; + strTmp[1] = 0; + + for (size_t i = 0; str[i] != 0; i++) { + if (str[i] == '\r') { + strTmp[0] = str[i]; + ST->ConOut->OutputString(ST->ConOut, strTmp); + + strTmp[0] = '\n'; + ST->ConOut->OutputString(ST->ConOut, strTmp); + } else { + strTmp[0] = str[i]; + ST->ConOut->OutputString(ST->ConOut, strTmp); + } + } +#endif // ifdef __DEBUG__ + + return *this; } /** @brief putc wrapper over EFI ConOut. */ -Boot::BootTextWriter& Boot::BootTextWriter::WriteCharacter(CharacterTypeUTF16 c) -{ +Boot::BootTextWriter& Boot::BootTextWriter::WriteCharacter(CharacterTypeUTF16 c) { #ifdef __DEBUG__ - EfiCharType str[2]; + EfiCharType str[2]; - str[0] = c; - str[1] = 0; - ST->ConOut->OutputString(ST->ConOut, str); -#endif // ifdef __DEBUG__ + str[0] = c; + str[1] = 0; + ST->ConOut->OutputString(ST->ConOut, str); +#endif // ifdef __DEBUG__ - return *this; + return *this; } -Boot::BootTextWriter& Boot::BootTextWriter::Write(const UInt64& x) -{ +Boot::BootTextWriter& Boot::BootTextWriter::Write(const UInt64& x) { #ifdef __DEBUG__ - this->_Write(x); - this->Write("h"); -#endif // ifdef __DEBUG__ + this->_Write(x); + this->Write("h"); +#endif // ifdef __DEBUG__ - return *this; + return *this; } -Boot::BootTextWriter& Boot::BootTextWriter::_Write(const UInt64& x) -{ +Boot::BootTextWriter& Boot::BootTextWriter::_Write(const UInt64& x) { #ifdef __DEBUG__ - UInt64 y = (x > 0 ? x : -x) / 16; - UInt64 h = (x > 0 ? x : -x) % 16; + UInt64 y = (x > 0 ? x : -x) / 16; + UInt64 h = (x > 0 ? x : -x) % 16; - if (y) - this->_Write(y); + if (y) this->_Write(y); - /* fail if the hex number is not base-16 */ - if (h > 16) - { - this->WriteCharacter('?'); - return *this; - } + /* fail if the hex number is not base-16 */ + if (h > 16) { + this->WriteCharacter('?'); + return *this; + } - if (y == ~0UL) - y = -y; + if (y == ~0UL) y = -y; - const char cNumbers[] = "0123456789ABCDEF"; + const char cNumbers[] = "0123456789ABCDEF"; - this->WriteCharacter(cNumbers[h]); -#endif // ifdef __DEBUG__ + this->WriteCharacter(cNumbers[h]); +#endif // ifdef __DEBUG__ - return *this; + return *this; } diff --git a/dev/boot/src/BootThread.cc b/dev/boot/src/BootThread.cc index b6236df8..ada864bb 100644 --- a/dev/boot/src/BootThread.cc +++ b/dev/boot/src/BootThread.cc @@ -1,18 +1,18 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ +#include <BootKit/BootKit.h> #include <BootKit/BootThread.h> #include <BootKit/Support.h> -#include <BootKit/BootKit.h> #include <FirmwareKit/EFI/API.h> -#include <KernelKit/PEF.h> -#include <KernelKit/PE.h> -#include <KernelKit/MSDOS.h> #include <CFKit/Utils.h> +#include <KernelKit/MSDOS.h> +#include <KernelKit/PE.h> +#include <KernelKit/PEF.h> #include <modules/CoreGfx/TextGfx.h> /// @brief External boot services symbol. @@ -20,211 +20,187 @@ EXTERN EfiBootServices* BS; /// @note BootThread doesn't parse the symbols so doesn't nullify them, .bss is though. -namespace Boot -{ - EXTERN_C Int32 rt_jump_to_address(VoidPtr code, HEL::BootInfoHeader* handover, UInt8* stack); +namespace Boot { +EXTERN_C Int32 rt_jump_to_address(VoidPtr code, HEL::BootInfoHeader* handover, UInt8* stack); - BootThread::BootThread(VoidPtr blob) - : fStartAddress(nullptr), fBlob(blob) - { - // detect the format. - const Char* blob_bytes = reinterpret_cast<char*>(fBlob); +BootThread::BootThread(VoidPtr blob) : fStartAddress(nullptr), fBlob(blob) { + // detect the format. + const Char* blob_bytes = reinterpret_cast<char*>(fBlob); - BootTextWriter writer; + BootTextWriter writer; - if (!blob_bytes) - { - // failed to provide a valid pointer. - return; - } + if (!blob_bytes) { + // failed to provide a valid pointer. + return; + } - if (blob_bytes[0] == kMagMz0 && - blob_bytes[1] == kMagMz1) - { - LDR_EXEC_HEADER_PTR header_ptr = CF::ldr_find_exec_header(blob_bytes); - LDR_OPTIONAL_HEADER_PTR opt_header_ptr = CF::ldr_find_opt_exec_header(blob_bytes); + if (blob_bytes[0] == kMagMz0 && blob_bytes[1] == kMagMz1) { + LDR_EXEC_HEADER_PTR header_ptr = CF::ldr_find_exec_header(blob_bytes); + LDR_OPTIONAL_HEADER_PTR opt_header_ptr = CF::ldr_find_opt_exec_header(blob_bytes); - if (!header_ptr || !opt_header_ptr) - return; + if (!header_ptr || !opt_header_ptr) return; #ifdef __NE_AMD64__ - if (header_ptr->Machine != kPeMachineAMD64 || - header_ptr->Signature != kPeSignature) - { - writer.Write("BootZ: Not a PE32+ executable.\r"); - return; - } + if (header_ptr->Machine != kPeMachineAMD64 || header_ptr->Signature != kPeSignature) { + writer.Write("BootZ: Not a PE32+ executable.\r"); + return; + } #elif defined(__NE_ARM64__) - if (header_ptr->Machine != kPeMachineARM64 || - header_ptr->Signature != kPeSignature) - { - writer.Write("BootZ: Not a PE32+ executable.\r"); - return; - } -#endif // __NE_AMD64__ || __NE_ARM64__ - - writer.Write("BootZ: PE32+ executable detected (NeKernel Subsystem).\r"); - - auto numSecs = header_ptr->NumberOfSections; - - writer.Write("BootZ: Major Linker Ver: ").Write(opt_header_ptr->MajorLinkerVersion).Write("\r"); - writer.Write("BootZ: Minor Linker Ver: ").Write(opt_header_ptr->MinorLinkerVersion).Write("\r"); - writer.Write("BootZ: Major Subsystem Ver: ").Write(opt_header_ptr->MajorSubsystemVersion).Write("\r"); - writer.Write("BootZ: Minor Subsystem Ver: ").Write(opt_header_ptr->MinorSubsystemVersion).Write("\r"); - writer.Write("BootZ: Magic: ").Write(header_ptr->Signature).Write("\r"); - - EfiPhysicalAddress loadStartAddress = opt_header_ptr->ImageBase; - loadStartAddress += opt_header_ptr->BaseOfData; - - writer.Write("BootZ: Image base: ").Write(loadStartAddress).Write("\r"); - - fStack = new UInt8[mib_cast(16)]; - - if (!fStack) - { - writer.Write("BootZ: Unable to allocate stack.\r"); - return; - } - - LDR_SECTION_HEADER_PTR sectPtr = (LDR_SECTION_HEADER_PTR)(((Char*)opt_header_ptr) + header_ptr->SizeOfOptionalHeader); - - constexpr auto sectionForCode = ".text"; - constexpr auto sectionForBootZ = ".ldr"; - - for (SizeT sectIndex = 0; sectIndex < numSecs; ++sectIndex) - { - LDR_SECTION_HEADER_PTR sect = §Ptr[sectIndex]; - - auto sz = sect->VirtualSize; - - if (sect->SizeOfRawData > 0) - sz = sect->SizeOfRawData; - - SetMem((VoidPtr)(loadStartAddress + sect->VirtualAddress), 0, sz); - - if (sect->SizeOfRawData > 0) - { - CopyMem((VoidPtr)(loadStartAddress + sect->VirtualAddress), - (VoidPtr)((UIntPtr)fBlob + sect->PointerToRawData), - sect->SizeOfRawData); - } - - if (StrCmp(sectionForCode, sect->Name) == 0) - { - fStartAddress = (VoidPtr)((UIntPtr)loadStartAddress + opt_header_ptr->AddressOfEntryPoint); - writer.Write("BootZ: Executable entry address: ").Write((UIntPtr)fStartAddress).Write("\r"); - } - else if (StrCmp(sectionForBootZ, sect->Name) == 0) - { - struct HANDOVER_INFORMATION_STUB - { - UInt64 HandoverMagic; - UInt32 HandoverType; - UInt32 HandoverPad; - UInt32 HandoverArch; - }* handover_struc = (struct HANDOVER_INFORMATION_STUB*)((UIntPtr)fBlob + sect->PointerToRawData); - - if (handover_struc->HandoverMagic != kHandoverMagic) - { + if (header_ptr->Machine != kPeMachineARM64 || header_ptr->Signature != kPeSignature) { + writer.Write("BootZ: Not a PE32+ executable.\r"); + return; + } +#endif // __NE_AMD64__ || __NE_ARM64__ + + writer.Write("BootZ: PE32+ executable detected (NeKernel Subsystem).\r"); + + auto numSecs = header_ptr->NumberOfSections; + + writer.Write("BootZ: Major Linker Ver: ").Write(opt_header_ptr->MajorLinkerVersion).Write("\r"); + writer.Write("BootZ: Minor Linker Ver: ").Write(opt_header_ptr->MinorLinkerVersion).Write("\r"); + writer.Write("BootZ: Major Subsystem Ver: ") + .Write(opt_header_ptr->MajorSubsystemVersion) + .Write("\r"); + writer.Write("BootZ: Minor Subsystem Ver: ") + .Write(opt_header_ptr->MinorSubsystemVersion) + .Write("\r"); + writer.Write("BootZ: Magic: ").Write(header_ptr->Signature).Write("\r"); + + EfiPhysicalAddress loadStartAddress = opt_header_ptr->ImageBase; + loadStartAddress += opt_header_ptr->BaseOfData; + + writer.Write("BootZ: Image base: ").Write(loadStartAddress).Write("\r"); + + fStack = new UInt8[mib_cast(16)]; + + if (!fStack) { + writer.Write("BootZ: Unable to allocate stack.\r"); + return; + } + + LDR_SECTION_HEADER_PTR sectPtr = + (LDR_SECTION_HEADER_PTR) (((Char*) opt_header_ptr) + header_ptr->SizeOfOptionalHeader); + + constexpr auto sectionForCode = ".text"; + constexpr auto sectionForBootZ = ".ldr"; + + for (SizeT sectIndex = 0; sectIndex < numSecs; ++sectIndex) { + LDR_SECTION_HEADER_PTR sect = §Ptr[sectIndex]; + + auto sz = sect->VirtualSize; + + if (sect->SizeOfRawData > 0) sz = sect->SizeOfRawData; + + SetMem((VoidPtr) (loadStartAddress + sect->VirtualAddress), 0, sz); + + if (sect->SizeOfRawData > 0) { + CopyMem((VoidPtr) (loadStartAddress + sect->VirtualAddress), + (VoidPtr) ((UIntPtr) fBlob + sect->PointerToRawData), sect->SizeOfRawData); + } + + if (StrCmp(sectionForCode, sect->Name) == 0) { + fStartAddress = + (VoidPtr) ((UIntPtr) loadStartAddress + opt_header_ptr->AddressOfEntryPoint); + writer.Write("BootZ: Executable entry address: ") + .Write((UIntPtr) fStartAddress) + .Write("\r"); + } else if (StrCmp(sectionForBootZ, sect->Name) == 0) { + struct HANDOVER_INFORMATION_STUB { + UInt64 HandoverMagic; + UInt32 HandoverType; + UInt32 HandoverPad; + UInt32 HandoverArch; + }* handover_struc = + (struct HANDOVER_INFORMATION_STUB*) ((UIntPtr) fBlob + sect->PointerToRawData); + + if (handover_struc->HandoverMagic != kHandoverMagic) { #ifdef __NE_AMD64__ - if (handover_struc->HandoverArch != HEL::kArchAMD64) - { - writer.Write("BootZ: Not an handover header, bad CPU...\r"); - } + if (handover_struc->HandoverArch != HEL::kArchAMD64) { + writer.Write("BootZ: Not an handover header, bad CPU...\r"); + } #elif defined(__NE_ARM64__) - if (handover_struc->HandoverArch != HEL::kArchARM64) - { - writer.Write("BootZ: Not an handover header, bad CPU...\r"); - } + if (handover_struc->HandoverArch != HEL::kArchARM64) { + writer.Write("BootZ: Not an handover header, bad CPU...\r"); + } #endif - writer.Write("BootZ: Not an handover header...\r"); - ::Boot::Stop(); - } - } - - writer.Write("BootZ: Raw offset: ").Write(sect->PointerToRawData).Write(" of ").Write(sect->Name).Write("\r"); - - CopyMem((VoidPtr)(loadStartAddress + sect->VirtualAddress), (VoidPtr)((UIntPtr)fBlob + sect->PointerToRawData), sect->SizeOfRawData); - } - } - else if (blob_bytes[0] == kPefMagic[0] && - blob_bytes[1] == kPefMagic[1] && - blob_bytes[2] == kPefMagic[2] && - blob_bytes[3] == kPefMagic[3]) - { - // ========================================= // - // PEF executable has been detected. - // ========================================= // - - fStartAddress = nullptr; - - writer.Write("BootZ: PEF executable detected, won't load it.\r"); - writer.Write("BootZ: note: PEF executables aren't supported for now.\r"); - } - else - { - writer.Write("BootZ: Invalid Executable.\r"); - } - } - - /// @note handover header has to be valid! - Int32 BootThread::Start(HEL::BootInfoHeader* handover, Bool own_stack) - { - fHandover = handover; - - if (!fStartAddress) - { - return kEfiFail; - } - - if (!fHandover) - { - return kEfiFail; - } - - BootTextWriter writer; - - writer.Write("BootZ: Starting: ").Write(fBlobName).Write("\r"); - writer.Write("BootZ: Handover address: ").Write((UIntPtr)fHandover).Write("\r"); - - if (own_stack) - { - writer.Write("BootZ: Using it's own stack.\r"); - writer.Write("BootZ: Stack address: ").Write((UIntPtr)&fStack[mib_cast(16) - 1]).Write("\r"); - writer.Write("BootZ: Stack size: ").Write(mib_cast(16)).Write("\r"); - - auto ret = rt_jump_to_address(fStartAddress, fHandover, &fStack[mib_cast(16) - 1]); - - // we don't need the stack anymore. - - delete[] fStack; - fStack = nullptr; - - return ret; - } - else - { - writer.Write("BootZ: Using Bootloader's stack.\r"); - - return reinterpret_cast<HEL::HandoverProc>(fStartAddress)(fHandover); - } - - return kEfiFail; - } - - const Char* BootThread::GetName() - { - return fBlobName; - } - - Void BootThread::SetName(const Char* name) - { - CopyMem(fBlobName, name, StrLen(name)); - } - - bool BootThread::IsValid() - { - return fStartAddress != nullptr; - } -} // namespace Boot
\ No newline at end of file + writer.Write("BootZ: Not an handover header...\r"); + ::Boot::Stop(); + } + } + + writer.Write("BootZ: Raw offset: ") + .Write(sect->PointerToRawData) + .Write(" of ") + .Write(sect->Name) + .Write("\r"); + + CopyMem((VoidPtr) (loadStartAddress + sect->VirtualAddress), + (VoidPtr) ((UIntPtr) fBlob + sect->PointerToRawData), sect->SizeOfRawData); + } + } else if (blob_bytes[0] == kPefMagic[0] && blob_bytes[1] == kPefMagic[1] && + blob_bytes[2] == kPefMagic[2] && blob_bytes[3] == kPefMagic[3]) { + // ========================================= // + // PEF executable has been detected. + // ========================================= // + + fStartAddress = nullptr; + + writer.Write("BootZ: PEF executable detected, won't load it.\r"); + writer.Write("BootZ: note: PEF executables aren't supported for now.\r"); + } else { + writer.Write("BootZ: Invalid Executable.\r"); + } +} + +/// @note handover header has to be valid! +Int32 BootThread::Start(HEL::BootInfoHeader* handover, Bool own_stack) { + fHandover = handover; + + if (!fStartAddress) { + return kEfiFail; + } + + if (!fHandover) { + return kEfiFail; + } + + BootTextWriter writer; + + writer.Write("BootZ: Starting: ").Write(fBlobName).Write("\r"); + writer.Write("BootZ: Handover address: ").Write((UIntPtr) fHandover).Write("\r"); + + if (own_stack) { + writer.Write("BootZ: Using it's own stack.\r"); + writer.Write("BootZ: Stack address: ").Write((UIntPtr) &fStack[mib_cast(16) - 1]).Write("\r"); + writer.Write("BootZ: Stack size: ").Write(mib_cast(16)).Write("\r"); + + auto ret = rt_jump_to_address(fStartAddress, fHandover, &fStack[mib_cast(16) - 1]); + + // we don't need the stack anymore. + + delete[] fStack; + fStack = nullptr; + + return ret; + } else { + writer.Write("BootZ: Using Bootloader's stack.\r"); + + return reinterpret_cast<HEL::HandoverProc>(fStartAddress)(fHandover); + } + + return kEfiFail; +} + +const Char* BootThread::GetName() { + return fBlobName; +} + +Void BootThread::SetName(const Char* name) { + CopyMem(fBlobName, name, StrLen(name)); +} + +bool BootThread::IsValid() { + return fStartAddress != nullptr; +} +} // namespace Boot
\ No newline at end of file diff --git a/dev/boot/src/HEL/AMD64/BootATA.cc b/dev/boot/src/HEL/AMD64/BootATA.cc index 8b1b5a0a..693513e0 100644 --- a/dev/boot/src/HEL/AMD64/BootATA.cc +++ b/dev/boot/src/HEL/AMD64/BootATA.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ @@ -15,9 +15,9 @@ * */ -#include <FirmwareKit/EFI.h> #include <BootKit/BootKit.h> #include <BootKit/HW/ATA.h> +#include <FirmwareKit/EFI.h> /// bugs: 0 @@ -25,159 +25,143 @@ using namespace Boot; #define kATADataLen (256) -static Boolean kATADetected = false; +static Boolean kATADetected = false; static UInt16 kATAData[kATADataLen] = {0}; Boolean boot_ata_detected(Void); -STATIC Boolean boot_ata_wait_io(UInt16 IO) -{ - for (int i = 0; i < 400; i++) - rt_in8(IO + ATA_REG_STATUS); +STATIC Boolean boot_ata_wait_io(UInt16 IO) { + for (int i = 0; i < 400; i++) rt_in8(IO + ATA_REG_STATUS); ATAWaitForIO_Retry: - auto status_rdy = rt_in8(IO + ATA_REG_STATUS); + auto status_rdy = rt_in8(IO + ATA_REG_STATUS); - if ((status_rdy & ATA_SR_BSY)) - goto ATAWaitForIO_Retry; + if ((status_rdy & ATA_SR_BSY)) goto ATAWaitForIO_Retry; ATAWaitForIO_Retry2: - status_rdy = rt_in8(IO + ATA_REG_STATUS); + status_rdy = rt_in8(IO + ATA_REG_STATUS); - if (status_rdy & ATA_SR_ERR) - return false; + if (status_rdy & ATA_SR_ERR) return false; - if (!(status_rdy & ATA_SR_DRDY)) - goto ATAWaitForIO_Retry2; + if (!(status_rdy & ATA_SR_DRDY)) goto ATAWaitForIO_Retry2; - return true; + return true; } -Void boot_ata_select(UInt16 Bus) -{ - if (Bus == ATA_PRIMARY_IO) - rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_PRIMARY_SEL); - else - rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_SECONDARY_SEL); +Void boot_ata_select(UInt16 Bus) { + if (Bus == ATA_PRIMARY_IO) + rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_PRIMARY_SEL); + else + rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_SECONDARY_SEL); } -Boolean boot_ata_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster) -{ - NE_UNUSED(Drive); +Boolean boot_ata_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster) { + NE_UNUSED(Drive); - if (boot_ata_detected()) - return true; + if (boot_ata_detected()) return true; - BootTextWriter writer; + BootTextWriter writer; - UInt16 IO = Bus; + UInt16 IO = Bus; - boot_ata_select(IO); + boot_ata_select(IO); - // Bus init, NEIN bit. - rt_out8(IO + ATA_REG_NEIN, 1); + // Bus init, NEIN bit. + rt_out8(IO + ATA_REG_NEIN, 1); - // identify until it's good. + // identify until it's good. ATAInit_Retry: - auto status_rdy = rt_in8(IO + ATA_REG_STATUS); + auto status_rdy = rt_in8(IO + ATA_REG_STATUS); - if (status_rdy & ATA_SR_ERR) - { - writer.Write( - L"BootZ: ATA: Not an IDE based drive.\r"); + if (status_rdy & ATA_SR_ERR) { + writer.Write(L"BootZ: ATA: Not an IDE based drive.\r"); - return false; - } + return false; + } - if ((status_rdy & ATA_SR_BSY)) - goto ATAInit_Retry; + if ((status_rdy & ATA_SR_BSY)) goto ATAInit_Retry; - rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); - /// fetch serial info - /// model, speed, number of sectors... + /// fetch serial info + /// model, speed, number of sectors... - boot_ata_wait_io(IO); + boot_ata_wait_io(IO); - for (SizeT indexData = 0ul; indexData < kATADataLen; ++indexData) - { - kATAData[indexData] = Kernel::HAL::rt_in16(IO + ATA_REG_DATA); - } + for (SizeT indexData = 0ul; indexData < kATADataLen; ++indexData) { + kATAData[indexData] = Kernel::HAL::rt_in16(IO + ATA_REG_DATA); + } - OutBus = - (Bus == ATA_PRIMARY_IO) ? BootDeviceATA::kPrimary : BootDeviceATA::kSecondary; + OutBus = (Bus == ATA_PRIMARY_IO) ? BootDeviceATA::kPrimary : BootDeviceATA::kSecondary; - OutMaster = (Bus == ATA_PRIMARY_IO) ? ATA_MASTER : ATA_SLAVE; + OutMaster = (Bus == ATA_PRIMARY_IO) ? ATA_MASTER : ATA_SLAVE; - return true; + return true; } -Void boot_ata_read(UInt64 Lba, UInt16 IO, UInt8 Master, CharacterTypeUTF8* Buf, SizeT SectorSz, SizeT Size) -{ - Lba /= SectorSz; +Void boot_ata_read(UInt64 Lba, UInt16 IO, UInt8 Master, CharacterTypeUTF8* Buf, SizeT SectorSz, + SizeT Size) { + Lba /= SectorSz; - UInt8 Command = ((!Master) ? 0xE0 : 0xF0); + UInt8 Command = ((!Master) ? 0xE0 : 0xF0); - boot_ata_wait_io(IO); - boot_ata_select(IO); + boot_ata_wait_io(IO); + boot_ata_select(IO); - rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); + rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); - rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + SectorSz) / SectorSz)); + rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + SectorSz) / SectorSz)); - rt_out8(IO + ATA_REG_LBA0, (Lba)&0xFF); - rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); - rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); - rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); + rt_out8(IO + ATA_REG_LBA0, (Lba) & 0xFF); + rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); + rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); + rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); - rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_READ_PIO); + rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_READ_PIO); - boot_ata_wait_io(IO); + boot_ata_wait_io(IO); - for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff) - { - boot_ata_wait_io(IO); - Buf[IndexOff] = Kernel::HAL::rt_in16(IO + ATA_REG_DATA); - boot_ata_wait_io(IO); - } + for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff) { + boot_ata_wait_io(IO); + Buf[IndexOff] = Kernel::HAL::rt_in16(IO + ATA_REG_DATA); + boot_ata_wait_io(IO); + } } -Void boot_ata_write(UInt64 Lba, UInt16 IO, UInt8 Master, CharacterTypeUTF8* Buf, SizeT SectorSz, SizeT Size) -{ - Lba /= SectorSz; +Void boot_ata_write(UInt64 Lba, UInt16 IO, UInt8 Master, CharacterTypeUTF8* Buf, SizeT SectorSz, + SizeT Size) { + Lba /= SectorSz; - UInt8 Command = ((!Master) ? 0xE0 : 0xF0); + UInt8 Command = ((!Master) ? 0xE0 : 0xF0); - boot_ata_wait_io(IO); - boot_ata_select(IO); + boot_ata_wait_io(IO); + boot_ata_select(IO); - rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); + rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); - rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + (SectorSz)) / SectorSz)); + rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + (SectorSz)) / SectorSz)); - rt_out8(IO + ATA_REG_LBA0, (Lba)&0xFF); - rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); - rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); - rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); + rt_out8(IO + ATA_REG_LBA0, (Lba) & 0xFF); + rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); + rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); + rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); - rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); + rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); - boot_ata_wait_io(IO); + boot_ata_wait_io(IO); - for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff) - { - boot_ata_wait_io(IO); - rt_out16(IO + ATA_REG_DATA, Buf[IndexOff]); - boot_ata_wait_io(IO); - } + for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff) { + boot_ata_wait_io(IO); + rt_out16(IO + ATA_REG_DATA, Buf[IndexOff]); + boot_ata_wait_io(IO); + } - boot_ata_wait_io(IO); + boot_ata_wait_io(IO); } /// @check is ATA detected? -Boolean boot_ata_detected(Void) -{ - return kATADetected; +Boolean boot_ata_detected(Void) { + return kATADetected; } /*** @@ -192,93 +176,79 @@ Boolean boot_ata_detected(Void) * @brief ATA Device constructor. * @param void none. */ -BootDeviceATA::BootDeviceATA() noexcept -{ - if (boot_ata_init(ATA_PRIMARY_IO, true, this->Leak().mBus, - this->Leak().mMaster) || - boot_ata_init(ATA_SECONDARY_IO, true, this->Leak().mBus, - this->Leak().mMaster)) - { - kATADetected = true; - } +BootDeviceATA::BootDeviceATA() noexcept { + if (boot_ata_init(ATA_PRIMARY_IO, true, this->Leak().mBus, this->Leak().mMaster) || + boot_ata_init(ATA_SECONDARY_IO, true, this->Leak().mBus, this->Leak().mMaster)) { + kATADetected = true; + } } /** * @brief Is ATA detected? */ -BootDeviceATA::operator bool() -{ - return boot_ata_detected(); +BootDeviceATA::operator bool() { + return boot_ata_detected(); } /** - @brief Read Buf from disk - @param Sz Sector size - @param Buf buffer + @brief Read Buf from disk + @param Sz Sector size + @param Buf buffer */ -BootDeviceATA& BootDeviceATA::Read(CharacterTypeUTF8* Buf, SizeT SectorSz) -{ - if (!boot_ata_detected()) - { - Leak().mErr = true; - return *this; - } +BootDeviceATA& BootDeviceATA::Read(CharacterTypeUTF8* Buf, SizeT SectorSz) { + if (!boot_ata_detected()) { + Leak().mErr = true; + return *this; + } - this->Leak().mErr = false; + this->Leak().mErr = false; - if (!Buf || SectorSz < 1) - return *this; + if (!Buf || SectorSz < 1) return *this; - boot_ata_read(this->Leak().mBase, this->Leak().mBus, this->Leak().mMaster, - Buf, SectorSz, this->Leak().mSize); + boot_ata_read(this->Leak().mBase, this->Leak().mBus, this->Leak().mMaster, Buf, SectorSz, + this->Leak().mSize); - return *this; + return *this; } /** - @brief Write Buf into disk - @param Sz Sector size - @param Buf buffer + @brief Write Buf into disk + @param Sz Sector size + @param Buf buffer */ -BootDeviceATA& BootDeviceATA::Write(CharacterTypeUTF8* Buf, SizeT SectorSz) -{ - if (!boot_ata_detected()) - { - Leak().mErr = true; - return *this; - } - - Leak().mErr = false; - - if (!Buf || SectorSz < 1 || this->Leak().mSize < 1) - { - Leak().mErr = true; - return *this; - } - - boot_ata_write(this->Leak().mBase, this->Leak().mBus, this->Leak().mMaster, - Buf, SectorSz, this->Leak().mSize); - - return *this; +BootDeviceATA& BootDeviceATA::Write(CharacterTypeUTF8* Buf, SizeT SectorSz) { + if (!boot_ata_detected()) { + Leak().mErr = true; + return *this; + } + + Leak().mErr = false; + + if (!Buf || SectorSz < 1 || this->Leak().mSize < 1) { + Leak().mErr = true; + return *this; + } + + boot_ata_write(this->Leak().mBase, this->Leak().mBus, this->Leak().mMaster, Buf, SectorSz, + this->Leak().mSize); + + return *this; } /** * @brief ATA trait getter. * @return BootDeviceATA::ATATrait& the drive config. */ -BootDeviceATA::ATATrait& BootDeviceATA::Leak() -{ - return mTrait; +BootDeviceATA::ATATrait& BootDeviceATA::Leak() { + return mTrait; } /*** - @brief Getter, gets the number of sectors inside the drive. + @brief Getter, gets the number of sectors inside the drive. */ -SizeT BootDeviceATA::GetSectorsCount() noexcept -{ - return (kATAData[61] << 16) | kATAData[60]; +SizeT BootDeviceATA::GetSectorsCount() noexcept { + return (kATAData[61] << 16) | kATAData[60]; } -SizeT BootDeviceATA::GetDiskSize() noexcept -{ - return this->GetSectorsCount() * BootDeviceATA::kSectorSize; +SizeT BootDeviceATA::GetDiskSize() noexcept { + return this->GetSectorsCount() * BootDeviceATA::kSectorSize; } diff --git a/dev/boot/src/HEL/AMD64/BootEFI.cc b/dev/boot/src/HEL/AMD64/BootEFI.cc index 6411383d..739876da 100644 --- a/dev/boot/src/HEL/AMD64/BootEFI.cc +++ b/dev/boot/src/HEL/AMD64/BootEFI.cc @@ -1,12 +1,11 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ #include <BootKit/BootKit.h> -#include <modules/CoreGfx/CoreGfx.h> -#include <modules/CoreGfx/TextGfx.h> +#include <BootKit/BootThread.h> #include <FirmwareKit/EFI.h> #include <FirmwareKit/EFI/API.h> #include <FirmwareKit/Handover.h> @@ -15,265 +14,249 @@ #include <KernelKit/PEF.h> #include <NewKit/Macros.h> #include <NewKit/Ref.h> -#include <BootKit/BootThread.h> #include <modules/CoreGfx/CoreGfx.h> +#include <modules/CoreGfx/TextGfx.h> // Makes the compiler shut up. #ifndef kMachineModel #define kMachineModel "OS" -#endif // !kMachineModel +#endif // !kMachineModel /** Graphics related. */ -STATIC EfiGraphicsOutputProtocol* kGop = nullptr; -STATIC UInt16 kGopStride = 0U; -STATIC EfiGUID kGopGuid; +STATIC EfiGraphicsOutputProtocol* kGop = nullptr; +STATIC UInt16 kGopStride = 0U; +STATIC EfiGUID kGopGuid; /** Related to jumping to the reset vector. */ EXTERN_C Void rt_reset_hardware(); /** - @brief Finds and stores the GOP object. + @brief Finds and stores the GOP object. */ -STATIC Bool boot_init_fb() noexcept -{ - kGopGuid = EfiGUID(EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID); - kGop = nullptr; +STATIC Bool boot_init_fb() noexcept { + kGopGuid = EfiGUID(EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID); + kGop = nullptr; - if (BS->LocateProtocol(&kGopGuid, nullptr, (VoidPtr*)&kGop) != kEfiOk) - return No; + if (BS->LocateProtocol(&kGopGuid, nullptr, (VoidPtr*) &kGop) != kEfiOk) return No; - kGopStride = 4; + kGopStride = 4; - return Yes; + return Yes; } EfiGUID kEfiGlobalNamespaceVarGUID = { - 0x8BE4DF61, 0x93CA, 0x11D2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C}}; + 0x8BE4DF61, 0x93CA, 0x11D2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C}}; /// @brief BootloaderMain EFI entrypoint. /// @param image_handle Handle of this image. /// @param sys_table The system table of it. /// @return nothing, never returns. -EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, - EfiSystemTable* sys_table) -{ - fw_init_efi(sys_table); ///! Init the EFI library. +EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, EfiSystemTable* sys_table) { + fw_init_efi(sys_table); ///! Init the EFI library. + + ST->ConOut->ClearScreen(sys_table->ConOut); + ST->ConOut->SetAttribute(sys_table->ConOut, kEFIYellow); + + ST->BootServices->SetWatchdogTimer(0, 0, 0, nullptr); + ST->ConOut->EnableCursor(ST->ConOut, false); - ST->ConOut->ClearScreen(sys_table->ConOut); - ST->ConOut->SetAttribute(sys_table->ConOut, kEFIYellow); + HEL::BootInfoHeader* handover_hdr = new HEL::BootInfoHeader(); - ST->BootServices->SetWatchdogTimer(0, 0, 0, nullptr); - ST->ConOut->EnableCursor(ST->ConOut, false); + UInt32 map_key = 0; + UInt32 size_struct_ptr = sizeof(EfiMemoryDescriptor); + EfiMemoryDescriptor* struct_ptr = nullptr; + UInt32 sz_desc = sizeof(EfiMemoryDescriptor); + UInt32 rev_desc = 0; - HEL::BootInfoHeader* handover_hdr = - new HEL::BootInfoHeader(); + Boot::BootTextWriter writer; - UInt32 map_key = 0; - UInt32 size_struct_ptr = sizeof(EfiMemoryDescriptor); - EfiMemoryDescriptor* struct_ptr = nullptr; - UInt32 sz_desc = sizeof(EfiMemoryDescriptor); - UInt32 rev_desc = 0; - - Boot::BootTextWriter writer; + if (!boot_init_fb()) { + writer.Write("BootZ: Invalid Framebuffer, can't boot to NeKernel.\r"); + Boot::Stop(); + } - if (!boot_init_fb()) - { - writer.Write("BootZ: Invalid Framebuffer, can't boot to NeKernel.\r"); - Boot::Stop(); - } - - for (SizeT index_vt = 0; index_vt < sys_table->NumberOfTableEntries; - ++index_vt) - { - Char* vendor_table = reinterpret_cast<Char*>( - sys_table->ConfigurationTable[index_vt].VendorTable); + for (SizeT index_vt = 0; index_vt < sys_table->NumberOfTableEntries; ++index_vt) { + Char* vendor_table = + reinterpret_cast<Char*>(sys_table->ConfigurationTable[index_vt].VendorTable); - // ACPI's 'RSD PTR', which contains the ACPI SDT (MADT, FACP...) - if (vendor_table[0] == 'R' && vendor_table[1] == 'S' && - vendor_table[2] == 'D' && vendor_table[3] == ' ' && - vendor_table[4] == 'P' && vendor_table[5] == 'T' && - vendor_table[6] == 'R' && vendor_table[7] == ' ') - { - handover_hdr->f_HardwareTables.f_VendorPtr = (VoidPtr)vendor_table; - break; - } - } + // ACPI's 'RSD PTR', which contains the ACPI SDT (MADT, FACP...) + if (vendor_table[0] == 'R' && vendor_table[1] == 'S' && vendor_table[2] == 'D' && + vendor_table[3] == ' ' && vendor_table[4] == 'P' && vendor_table[5] == 'T' && + vendor_table[6] == 'R' && vendor_table[7] == ' ') { + handover_hdr->f_HardwareTables.f_VendorPtr = (VoidPtr) vendor_table; + break; + } + } - // ------------------------------------------ // - // draw background color. - // ------------------------------------------ // + // ------------------------------------------ // + // draw background color. + // ------------------------------------------ // - handover_hdr->f_GOP.f_The = kGop->Mode->FrameBufferBase; - handover_hdr->f_GOP.f_Width = kGop->Mode->Info->VerticalResolution; - handover_hdr->f_GOP.f_Height = kGop->Mode->Info->HorizontalResolution; - handover_hdr->f_GOP.f_PixelPerLine = kGop->Mode->Info->PixelsPerScanLine; - handover_hdr->f_GOP.f_PixelFormat = kGop->Mode->Info->PixelFormat; - handover_hdr->f_GOP.f_Size = kGop->Mode->FrameBufferSize; + handover_hdr->f_GOP.f_The = kGop->Mode->FrameBufferBase; + handover_hdr->f_GOP.f_Width = kGop->Mode->Info->VerticalResolution; + handover_hdr->f_GOP.f_Height = kGop->Mode->Info->HorizontalResolution; + handover_hdr->f_GOP.f_PixelPerLine = kGop->Mode->Info->PixelsPerScanLine; + handover_hdr->f_GOP.f_PixelFormat = kGop->Mode->Info->PixelFormat; + handover_hdr->f_GOP.f_Size = kGop->Mode->FrameBufferSize; - // ------------------------------------------- // - // Grab MP services, extended to runtime. // - // ------------------------------------------- // + // ------------------------------------------- // + // Grab MP services, extended to runtime. // + // ------------------------------------------- // - EfiGUID guid_mp = EfiGUID(EFI_MP_SERVICES_PROTOCOL_GUID); - EfiMpServicesProtocol* mp = nullptr; + EfiGUID guid_mp = EfiGUID(EFI_MP_SERVICES_PROTOCOL_GUID); + EfiMpServicesProtocol* mp = nullptr; - BS->LocateProtocol(&guid_mp, nullptr, reinterpret_cast<VoidPtr*>(&mp)); + BS->LocateProtocol(&guid_mp, nullptr, reinterpret_cast<VoidPtr*>(&mp)); - handover_hdr->f_HardwareTables.f_MpPtr = reinterpret_cast<VoidPtr>(mp); + handover_hdr->f_HardwareTables.f_MpPtr = reinterpret_cast<VoidPtr>(mp); - kHandoverHeader = handover_hdr; + kHandoverHeader = handover_hdr; - FB::fb_clear_video(); + FB::fb_clear_video(); - UInt32 cnt_enabled = 0; - UInt32 cnt_disabled = 0; + UInt32 cnt_enabled = 0; + UInt32 cnt_disabled = 0; - if (mp) - { - mp->GetNumberOfProcessors(mp, &cnt_disabled, &cnt_enabled); - handover_hdr->f_HardwareTables.f_MultiProcessingEnabled = cnt_enabled > 1; - } - else - { - handover_hdr->f_HardwareTables.f_MultiProcessingEnabled = NO; - } + if (mp) { + mp->GetNumberOfProcessors(mp, &cnt_disabled, &cnt_enabled); + handover_hdr->f_HardwareTables.f_MultiProcessingEnabled = cnt_enabled > 1; + } else { + handover_hdr->f_HardwareTables.f_MultiProcessingEnabled = NO; + } - // Fill handover header now. + // Fill handover header now. - handover_hdr->f_BitMapStart = nullptr; /* Start of bitmap. */ - handover_hdr->f_BitMapSize = kHandoverBitMapSz; /* Size of bitmap in bytes. */ + handover_hdr->f_BitMapStart = nullptr; /* Start of bitmap. */ + handover_hdr->f_BitMapSize = kHandoverBitMapSz; /* Size of bitmap in bytes. */ - Int32 trials = 5 * 10000000; + Int32 trials = 5 * 10000000; - writer.Write("BootZ: Welcome to BootZ.\r"); - writer.Write("BootZ: Allocating sufficent memory, trying 4GB...\r"); + writer.Write("BootZ: Welcome to BootZ.\r"); + writer.Write("BootZ: Allocating sufficent memory, trying 4GB...\r"); - while (BS->AllocatePool(EfiLoaderData, handover_hdr->f_BitMapSize, &handover_hdr->f_BitMapStart) != kEfiOk) - { - --trials; + while (BS->AllocatePool(EfiLoaderData, handover_hdr->f_BitMapSize, + &handover_hdr->f_BitMapStart) != kEfiOk) { + --trials; - if (!trials) - { - writer.Write("BootZ: Unable to allocate sufficent memory, trying again with 2GB...\r"); + if (!trials) { + writer.Write("BootZ: Unable to allocate sufficent memory, trying again with 2GB...\r"); - trials = 3 * 10000000; + trials = 3 * 10000000; - handover_hdr->f_BitMapSize = kHandoverBitMapSz / 2; /* Size of bitmap in bytes. */ + handover_hdr->f_BitMapSize = kHandoverBitMapSz / 2; /* Size of bitmap in bytes. */ - while (BS->AllocatePool(EfiLoaderData, handover_hdr->f_BitMapSize, &handover_hdr->f_BitMapStart) != kEfiOk) - { - --trials; + while (BS->AllocatePool(EfiLoaderData, handover_hdr->f_BitMapSize, + &handover_hdr->f_BitMapStart) != kEfiOk) { + --trials; - if (!trials) - { - writer.Write("BootZ: Unable to allocate sufficent memory, aborting...\r"); - Boot::Stop(); - } - } - } - } + if (!trials) { + writer.Write("BootZ: Unable to allocate sufficent memory, aborting...\r"); + Boot::Stop(); + } + } + } + } - handover_hdr->f_FirmwareCustomTables[0] = (VoidPtr)BS; - handover_hdr->f_FirmwareCustomTables[1] = (VoidPtr)ST; + handover_hdr->f_FirmwareCustomTables[0] = (VoidPtr) BS; + handover_hdr->f_FirmwareCustomTables[1] = (VoidPtr) ST; - // ------------------------------------------ // - // If we succeed in reading the blob, then execute it. - // ------------------------------------------ // + // ------------------------------------------ // + // If we succeed in reading the blob, then execute it. + // ------------------------------------------ // - Boot::BootFileReader reader_syschk(L"chk.efi", image_handle); - reader_syschk.ReadAll(0); + Boot::BootFileReader reader_syschk(L"chk.efi", image_handle); + reader_syschk.ReadAll(0); - Boot::BootThread* syschk_thread = nullptr; + Boot::BootThread* syschk_thread = nullptr; - if (reader_syschk.Blob()) - { - syschk_thread = new Boot::BootThread(reader_syschk.Blob()); - syschk_thread->SetName("BootZ/SysChk"); + if (reader_syschk.Blob()) { + syschk_thread = new Boot::BootThread(reader_syschk.Blob()); + syschk_thread->SetName("BootZ/SysChk"); - syschk_thread->Start(handover_hdr, NO); - } + syschk_thread->Start(handover_hdr, NO); + } - BS->GetMemoryMap(&size_struct_ptr, struct_ptr, &map_key, &sz_desc, &rev_desc); + BS->GetMemoryMap(&size_struct_ptr, struct_ptr, &map_key, &sz_desc, &rev_desc); - handover_hdr->f_FirmwareVendorLen = Boot::BStrLen(sys_table->FirmwareVendor); + handover_hdr->f_FirmwareVendorLen = Boot::BStrLen(sys_table->FirmwareVendor); - handover_hdr->f_Magic = kHandoverMagic; - handover_hdr->f_Version = kHandoverVersion; + handover_hdr->f_Magic = kHandoverMagic; + handover_hdr->f_Version = kHandoverVersion; - handover_hdr->f_HardwareTables.f_ImageKey = map_key; - handover_hdr->f_HardwareTables.f_ImageHandle = image_handle; + handover_hdr->f_HardwareTables.f_ImageKey = map_key; + handover_hdr->f_HardwareTables.f_ImageHandle = image_handle; - // Provide fimware vendor name. + // Provide fimware vendor name. - Boot::BCopyMem(handover_hdr->f_FirmwareVendorName, sys_table->FirmwareVendor, - handover_hdr->f_FirmwareVendorLen); + Boot::BCopyMem(handover_hdr->f_FirmwareVendorName, sys_table->FirmwareVendor, + handover_hdr->f_FirmwareVendorLen); - handover_hdr->f_FirmwareVendorLen = Boot::BStrLen(sys_table->FirmwareVendor); - // Assign to global 'kHandoverHeader'. + handover_hdr->f_FirmwareVendorLen = Boot::BStrLen(sys_table->FirmwareVendor); + // Assign to global 'kHandoverHeader'. - WideChar kernel_path[256U] = L"krnl.efi"; - UInt32 kernel_path_sz = 256U; + WideChar kernel_path[256U] = L"krnl.efi"; + UInt32 kernel_path_sz = 256U; - if (ST->RuntimeServices->GetVariable(L"/props/boot_path", kEfiGlobalNamespaceVarGUID, nullptr, &kernel_path_sz, kernel_path) != kEfiOk) - { - /// access attributes (in order) - /// EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS - UInt32 attr = 0x00000001 | 0x00000002 | 0x00000004; + if (ST->RuntimeServices->GetVariable(L"/props/boot_path", kEfiGlobalNamespaceVarGUID, nullptr, + &kernel_path_sz, kernel_path) != kEfiOk) { + /// access attributes (in order) + /// EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS + UInt32 attr = 0x00000001 | 0x00000002 | 0x00000004; - ST->RuntimeServices->SetVariable(L"/props/boot_path", kEfiGlobalNamespaceVarGUID, &attr, &kernel_path_sz, kernel_path); - } + ST->RuntimeServices->SetVariable(L"/props/boot_path", kEfiGlobalNamespaceVarGUID, &attr, + &kernel_path_sz, kernel_path); + } - UInt32 sz_ver = sizeof(UInt64); - UInt64 ver = KERNEL_VERSION_BCD; + UInt32 sz_ver = sizeof(UInt64); + UInt64 ver = KERNEL_VERSION_BCD; - ST->RuntimeServices->GetVariable(L"/props/kern_ver", kEfiGlobalNamespaceVarGUID, nullptr, &sz_ver, &ver); + ST->RuntimeServices->GetVariable(L"/props/kern_ver", kEfiGlobalNamespaceVarGUID, nullptr, &sz_ver, + &ver); - if (ver != KERNEL_VERSION_BCD) - { - ver = KERNEL_VERSION_BCD; + if (ver != KERNEL_VERSION_BCD) { + ver = KERNEL_VERSION_BCD; - ST->RuntimeServices->SetVariable(L"/props/kern_ver", kEfiGlobalNamespaceVarGUID, nullptr, &sz_ver, &ver); - writer.Write("BootZ: version has been updated: ").Write(ver).Write("\r"); - } + ST->RuntimeServices->SetVariable(L"/props/kern_ver", kEfiGlobalNamespaceVarGUID, nullptr, + &sz_ver, &ver); + writer.Write("BootZ: version has been updated: ").Write(ver).Write("\r"); + } - writer.Write("BootZ: version: ").Write(ver).Write("\r"); + writer.Write("BootZ: version: ").Write(ver).Write("\r"); - // boot to kernel, if not netboot this. + // boot to kernel, if not netboot this. - Boot::BootFileReader reader_kernel(kernel_path, image_handle); + Boot::BootFileReader reader_kernel(kernel_path, image_handle); - reader_kernel.ReadAll(0); + reader_kernel.ReadAll(0); - // ------------------------------------------ // - // If we succeed in reading the blob, then execute it. - // ------------------------------------------ // + // ------------------------------------------ // + // If we succeed in reading the blob, then execute it. + // ------------------------------------------ // - if (reader_kernel.Blob()) - { - // ------------------------------------------ // - // null these fields, to avoid being reused later. - // ------------------------------------------ // + if (reader_kernel.Blob()) { + // ------------------------------------------ // + // null these fields, to avoid being reused later. + // ------------------------------------------ // - auto kernel_thread = Boot::BootThread(reader_kernel.Blob()); + auto kernel_thread = Boot::BootThread(reader_kernel.Blob()); - kernel_thread.SetName("BootZ/NeKernel"); + kernel_thread.SetName("BootZ/NeKernel"); - handover_hdr->f_KernelImage = reader_kernel.Blob(); - handover_hdr->f_KernelSz = reader_kernel.Size(); + handover_hdr->f_KernelImage = reader_kernel.Blob(); + handover_hdr->f_KernelSz = reader_kernel.Size(); - kernel_thread.Start(handover_hdr, YES); - } + kernel_thread.Start(handover_hdr, YES); + } - Boot::BootFileReader reader_netboot(L"net.efi", image_handle); - reader_netboot.ReadAll(0); + Boot::BootFileReader reader_netboot(L"net.efi", image_handle); + reader_netboot.ReadAll(0); - if (!reader_netboot.Blob()) - return kEfiFail; + if (!reader_netboot.Blob()) return kEfiFail; - auto netboot_thread = Boot::BootThread(reader_netboot.Blob()); - netboot_thread.SetName("BootZ/BootNet"); + auto netboot_thread = Boot::BootThread(reader_netboot.Blob()); + netboot_thread.SetName("BootZ/BootNet"); - return netboot_thread.Start(handover_hdr, NO); + return netboot_thread.Start(handover_hdr, NO); } diff --git a/dev/boot/src/HEL/AMD64/BootPlatform.cc b/dev/boot/src/HEL/AMD64/BootPlatform.cc index 1a1f9b89..8b4d57c4 100644 --- a/dev/boot/src/HEL/AMD64/BootPlatform.cc +++ b/dev/boot/src/HEL/AMD64/BootPlatform.cc @@ -1,50 +1,44 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ +#include <BootKit/BootKit.h> #include <BootKit/Platform.h> #include <BootKit/Protocol.h> -#include <BootKit/BootKit.h> #ifdef __BOOTZ_STANDALONE__ using namespace Boot; -EXTERN_C void rt_hlt() -{ - asm volatile("hlt"); +EXTERN_C void rt_hlt() { + asm volatile("hlt"); } -EXTERN_C void rt_cli() -{ - asm volatile("cli"); +EXTERN_C void rt_cli() { + asm volatile("cli"); } -EXTERN_C void rt_sti() -{ - asm volatile("sti"); +EXTERN_C void rt_sti() { + asm volatile("sti"); } -EXTERN_C void rt_cld() -{ - asm volatile("cld"); +EXTERN_C void rt_cld() { + asm volatile("cld"); } -EXTERN_C void rt_std() -{ - asm volatile("std"); +EXTERN_C void rt_std() { + asm volatile("std"); } #else #include <HALKit/AMD64/Processor.h> -void rt_hlt() -{ - Kernel::HAL::rt_halt(); +void rt_hlt() { + Kernel::HAL::rt_halt(); } -#endif // __BOOTZ_STANDALONE__ +#endif // __BOOTZ_STANDALONE__ diff --git a/dev/boot/src/HEL/AMD64/BootSATA.cc b/dev/boot/src/HEL/AMD64/BootSATA.cc index e60aebde..ef5d2096 100644 --- a/dev/boot/src/HEL/AMD64/BootSATA.cc +++ b/dev/boot/src/HEL/AMD64/BootSATA.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ @@ -15,6 +15,6 @@ * */ +#include <BootKit/HW/SATA.h> #include <BootKit/Platform.h> #include <BootKit/Protocol.h> -#include <BootKit/HW/SATA.h> diff --git a/dev/boot/src/HEL/ARM64/BootEFI.cc b/dev/boot/src/HEL/ARM64/BootEFI.cc index 9132cec1..1e5b62f3 100644 --- a/dev/boot/src/HEL/ARM64/BootEFI.cc +++ b/dev/boot/src/HEL/ARM64/BootEFI.cc @@ -1,12 +1,11 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ #include <BootKit/BootKit.h> -#include <modules/CoreGfx/CoreGfx.h> -#include <modules/CoreGfx/TextGfx.h> +#include <BootKit/BootThread.h> #include <FirmwareKit/EFI.h> #include <FirmwareKit/EFI/API.h> #include <FirmwareKit/Handover.h> @@ -15,8 +14,8 @@ #include <KernelKit/PEF.h> #include <NewKit/Macros.h> #include <NewKit/Ref.h> -#include <BootKit/BootThread.h> #include <modules/CoreGfx/CoreGfx.h> +#include <modules/CoreGfx/TextGfx.h> #ifndef kExpectedWidth #define kExpectedWidth (800) @@ -28,43 +27,39 @@ /** Graphics related. */ -STATIC EfiGraphicsOutputProtocol* kGop = nullptr; -STATIC UInt16 kGopStride = 0U; -STATIC EfiGUID kGopGuid; +STATIC EfiGraphicsOutputProtocol* kGop = nullptr; +STATIC UInt16 kGopStride = 0U; +STATIC EfiGUID kGopGuid; EXTERN_C Void rt_reset_hardware(); EXTERN EfiBootServices* BS; /** - @brief Finds and stores the GOP object. + @brief Finds and stores the GOP object. */ -STATIC Bool boot_init_fb() noexcept -{ - kGopGuid = EfiGUID(EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID); - kGop = nullptr; +STATIC Bool boot_init_fb() noexcept { + kGopGuid = EfiGUID(EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID); + kGop = nullptr; - if (BS->LocateProtocol(&kGopGuid, nullptr, (VoidPtr*)&kGop) != kEfiOk) - return No; + if (BS->LocateProtocol(&kGopGuid, nullptr, (VoidPtr*) &kGop) != kEfiOk) return No; - kGopStride = 4; + kGopStride = 4; - for (SizeT i = 0; i < kGop->Mode->MaxMode; ++i) - { - EfiGraphicsOutputProtocolModeInformation* infoPtr = nullptr; - UInt32 sz = 0U; + for (SizeT i = 0; i < kGop->Mode->MaxMode; ++i) { + EfiGraphicsOutputProtocolModeInformation* infoPtr = nullptr; + UInt32 sz = 0U; - kGop->QueryMode(kGop, i, &sz, &infoPtr); + kGop->QueryMode(kGop, i, &sz, &infoPtr); - if (infoPtr->HorizontalResolution == kExpectedWidth && - infoPtr->VerticalResolution == kExpectedHeight) - { - kGop->SetMode(kGop, i); - return Yes; - } - } + if (infoPtr->HorizontalResolution == kExpectedWidth && + infoPtr->VerticalResolution == kExpectedHeight) { + kGop->SetMode(kGop, i); + return Yes; + } + } - return No; + return No; } EXTERN EfiBootServices* BS; @@ -73,179 +68,167 @@ EXTERN EfiBootServices* BS; /// @param image_handle Handle of this image. /// @param sys_table The system table of it. /// @return nothing, never returns. -EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, - EfiSystemTable* sys_table) -{ - fw_init_efi(sys_table); ///! Init the EFI library. +EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, EfiSystemTable* sys_table) { + fw_init_efi(sys_table); ///! Init the EFI library. - HEL::BootInfoHeader* handover_hdr = - new HEL::BootInfoHeader(); + HEL::BootInfoHeader* handover_hdr = new HEL::BootInfoHeader(); - UInt32 map_key = 0; + UInt32 map_key = 0; #ifdef ZBA_USE_FB - if (!boot_init_fb()) - return 1; ///! Init the GOP. - - for (SizeT index_vt = 0; index_vt < sys_table->NumberOfTableEntries; - ++index_vt) - { - Char* vendor_table = reinterpret_cast<Char*>( - sys_table->ConfigurationTable[index_vt].VendorTable); - - // ACPI's 'RSD PTR', which contains the ACPI SDT (MADT, FACP...) - if (vendor_table[0] == 'R' && vendor_table[1] == 'S' && - vendor_table[2] == 'D' && vendor_table[3] == ' ' && - vendor_table[4] == 'P' && vendor_table[5] == 'T' && - vendor_table[6] == 'R' && vendor_table[7] == ' ') - { - handover_hdr->f_HardwareTables.f_VendorPtr = (VoidPtr)vendor_table; - break; - } - } + if (!boot_init_fb()) return 1; ///! Init the GOP. + + for (SizeT index_vt = 0; index_vt < sys_table->NumberOfTableEntries; ++index_vt) { + Char* vendor_table = + reinterpret_cast<Char*>(sys_table->ConfigurationTable[index_vt].VendorTable); + + // ACPI's 'RSD PTR', which contains the ACPI SDT (MADT, FACP...) + if (vendor_table[0] == 'R' && vendor_table[1] == 'S' && vendor_table[2] == 'D' && + vendor_table[3] == ' ' && vendor_table[4] == 'P' && vendor_table[5] == 'T' && + vendor_table[6] == 'R' && vendor_table[7] == ' ') { + handover_hdr->f_HardwareTables.f_VendorPtr = (VoidPtr) vendor_table; + break; + } + } - // ------------------------------------------ // - // draw background color. - // ------------------------------------------ // + // ------------------------------------------ // + // draw background color. + // ------------------------------------------ // - handover_hdr->f_GOP.f_The = kGop->Mode->FrameBufferBase; - handover_hdr->f_GOP.f_Width = kGop->Mode->Info->VerticalResolution; - handover_hdr->f_GOP.f_Height = kGop->Mode->Info->HorizontalResolution; - handover_hdr->f_GOP.f_PixelPerLine = kGop->Mode->Info->PixelsPerScanLine; - handover_hdr->f_GOP.f_PixelFormat = kGop->Mode->Info->PixelFormat; - handover_hdr->f_GOP.f_Size = kGop->Mode->FrameBufferSize; -#endif // ZBA_USE_FB + handover_hdr->f_GOP.f_The = kGop->Mode->FrameBufferBase; + handover_hdr->f_GOP.f_Width = kGop->Mode->Info->VerticalResolution; + handover_hdr->f_GOP.f_Height = kGop->Mode->Info->HorizontalResolution; + handover_hdr->f_GOP.f_PixelPerLine = kGop->Mode->Info->PixelsPerScanLine; + handover_hdr->f_GOP.f_PixelFormat = kGop->Mode->Info->PixelFormat; + handover_hdr->f_GOP.f_Size = kGop->Mode->FrameBufferSize; +#endif // ZBA_USE_FB - // ------------------------------------------- // - // Grab MP services, extended to runtime. // - // ------------------------------------------- // + // ------------------------------------------- // + // Grab MP services, extended to runtime. // + // ------------------------------------------- // - EfiGUID guid_mp = EfiGUID(EFI_MP_SERVICES_PROTOCOL_GUID); - EfiMpServicesProtocol* mp = nullptr; + EfiGUID guid_mp = EfiGUID(EFI_MP_SERVICES_PROTOCOL_GUID); + EfiMpServicesProtocol* mp = nullptr; - BS->LocateProtocol(&guid_mp, nullptr, reinterpret_cast<VoidPtr*>(&mp)); - handover_hdr->f_HardwareTables.f_MpPtr = reinterpret_cast<VoidPtr>(mp); + BS->LocateProtocol(&guid_mp, nullptr, reinterpret_cast<VoidPtr*>(&mp)); + handover_hdr->f_HardwareTables.f_MpPtr = reinterpret_cast<VoidPtr>(mp); - // Assign to global 'kHandoverHeader'. - kHandoverHeader = handover_hdr; + // Assign to global 'kHandoverHeader'. + kHandoverHeader = handover_hdr; - fb_init(); + fb_init(); - FB::fb_clear_video(); + FB::fb_clear_video(); - FBDrawBitMapInRegion(zka_disk, NE_DISK_WIDTH, NE_DISK_HEIGHT, (kHandoverHeader->f_GOP.f_Width - NE_DISK_WIDTH) / 2, (kHandoverHeader->f_GOP.f_Height - NE_DISK_HEIGHT) / 2); + FBDrawBitMapInRegion(zka_disk, NE_DISK_WIDTH, NE_DISK_HEIGHT, + (kHandoverHeader->f_GOP.f_Width - NE_DISK_WIDTH) / 2, + (kHandoverHeader->f_GOP.f_Height - NE_DISK_HEIGHT) / 2); - fb_clear(); + fb_clear(); - UInt32 cnt_enabled = 0; - UInt32 cnt_disabled = 0; + UInt32 cnt_enabled = 0; + UInt32 cnt_disabled = 0; - if (mp) - { - mp->GetNumberOfProcessors(mp, &cnt_disabled, &cnt_enabled); - handover_hdr->f_HardwareTables.f_MultiProcessingEnabled = cnt_enabled > 1; - } - else - { - handover_hdr->f_HardwareTables.f_MultiProcessingEnabled = NO; - } + if (mp) { + mp->GetNumberOfProcessors(mp, &cnt_disabled, &cnt_enabled); + handover_hdr->f_HardwareTables.f_MultiProcessingEnabled = cnt_enabled > 1; + } else { + handover_hdr->f_HardwareTables.f_MultiProcessingEnabled = NO; + } - //-------------------------------------------------------------// - // Allocate heap. - //-------------------------------------------------------------// + //-------------------------------------------------------------// + // Allocate heap. + //-------------------------------------------------------------// - Boot::BootTextWriter writer; + Boot::BootTextWriter writer; - handover_hdr->f_BitMapStart = nullptr; /* Start of bitmap. */ - handover_hdr->f_BitMapSize = kHandoverBitMapSz; /* Size of bitmap in bytes. */ - Int32 trials = 5 * 10000000; + handover_hdr->f_BitMapStart = nullptr; /* Start of bitmap. */ + handover_hdr->f_BitMapSize = kHandoverBitMapSz; /* Size of bitmap in bytes. */ + Int32 trials = 5 * 10000000; - while (BS->AllocatePool(EfiLoaderData, handover_hdr->f_BitMapSize, &handover_hdr->f_BitMapStart) != kEfiOk) - { - --trials; + while (BS->AllocatePool(EfiLoaderData, handover_hdr->f_BitMapSize, + &handover_hdr->f_BitMapStart) != kEfiOk) { + --trials; - if (!trials) - { - writer.Write("BootZ: Unable to allocate sufficent memory, trying again with 2GB...\r"); + if (!trials) { + writer.Write("BootZ: Unable to allocate sufficent memory, trying again with 2GB...\r"); - trials = 3 * 10000000; + trials = 3 * 10000000; - handover_hdr->f_BitMapSize = kHandoverBitMapSz / 2; /* Size of bitmap in bytes. */ + handover_hdr->f_BitMapSize = kHandoverBitMapSz / 2; /* Size of bitmap in bytes. */ - while (BS->AllocatePool(EfiLoaderData, handover_hdr->f_BitMapSize, &handover_hdr->f_BitMapStart) != kEfiOk) - { - --trials; + while (BS->AllocatePool(EfiLoaderData, handover_hdr->f_BitMapSize, + &handover_hdr->f_BitMapStart) != kEfiOk) { + --trials; - if (!trials) - { - writer.Write("BootZ: Unable to allocate sufficent memory, aborting...\r"); - Boot::Stop(); - } - } - } - } + if (!trials) { + writer.Write("BootZ: Unable to allocate sufficent memory, aborting...\r"); + Boot::Stop(); + } + } + } + } - Boot::BootFileReader reader_syschk(L"chk.efi", image_handle); - reader_syschk.ReadAll(0); + Boot::BootFileReader reader_syschk(L"chk.efi", image_handle); + reader_syschk.ReadAll(0); - Boot::BootThread* syschk_thread = nullptr; + Boot::BootThread* syschk_thread = nullptr; - if (reader_syschk.Blob()) - { - syschk_thread = new Boot::BootThread(reader_syschk.Blob()); - syschk_thread->SetName("BootZ: System Check"); + if (reader_syschk.Blob()) { + syschk_thread = new Boot::BootThread(reader_syschk.Blob()); + syschk_thread->SetName("BootZ: System Check"); - if (syschk_thread->Start(handover_hdr, NO) != kEfiOk) - { - fb_init(); + if (syschk_thread->Start(handover_hdr, NO) != kEfiOk) { + fb_init(); - FB::fb_clear_video(); + FB::fb_clear_video(); - FBDrawBitMapInRegion(zka_no_disk, NE_NO_DISK_WIDTH, NE_NO_DISK_HEIGHT, (kHandoverHeader->f_GOP.f_Width - NE_NO_DISK_WIDTH) / 2, (kHandoverHeader->f_GOP.f_Height - NE_NO_DISK_HEIGHT) / 2); + FBDrawBitMapInRegion(zka_no_disk, NE_NO_DISK_WIDTH, NE_NO_DISK_HEIGHT, + (kHandoverHeader->f_GOP.f_Width - NE_NO_DISK_WIDTH) / 2, + (kHandoverHeader->f_GOP.f_Height - NE_NO_DISK_HEIGHT) / 2); - fb_clear(); - } - } + fb_clear(); + } + } - // ------------------------------------------ // - // null these fields, to avoid being reused later. - // ------------------------------------------ // + // ------------------------------------------ // + // null these fields, to avoid being reused later. + // ------------------------------------------ // - handover_hdr->f_FirmwareCustomTables[0] = nullptr; - handover_hdr->f_FirmwareCustomTables[1] = nullptr; + handover_hdr->f_FirmwareCustomTables[0] = nullptr; + handover_hdr->f_FirmwareCustomTables[1] = nullptr; - handover_hdr->f_FirmwareVendorLen = Boot::BStrLen(sys_table->FirmwareVendor); + handover_hdr->f_FirmwareVendorLen = Boot::BStrLen(sys_table->FirmwareVendor); - handover_hdr->f_Magic = kHandoverMagic; - handover_hdr->f_Version = kHandoverVersion; + handover_hdr->f_Magic = kHandoverMagic; + handover_hdr->f_Version = kHandoverVersion; - // Provide fimware vendor name. + // Provide fimware vendor name. - Boot::BCopyMem(handover_hdr->f_FirmwareVendorName, sys_table->FirmwareVendor, - handover_hdr->f_FirmwareVendorLen); + Boot::BCopyMem(handover_hdr->f_FirmwareVendorName, sys_table->FirmwareVendor, + handover_hdr->f_FirmwareVendorLen); - handover_hdr->f_FirmwareVendorLen = Boot::BStrLen(sys_table->FirmwareVendor); + handover_hdr->f_FirmwareVendorLen = Boot::BStrLen(sys_table->FirmwareVendor); - Boot::BootFileReader reader_kernel(L"krnl.efi", image_handle); + Boot::BootFileReader reader_kernel(L"krnl.efi", image_handle); - reader_kernel.ReadAll(0); + reader_kernel.ReadAll(0); - // ------------------------------------------ // - // If we succeed in reading the blob, then execute it. - // ------------------------------------------ // + // ------------------------------------------ // + // If we succeed in reading the blob, then execute it. + // ------------------------------------------ // - if (reader_kernel.Blob()) - { - auto kernel_thread = Boot::BootThread(reader_kernel.Blob()); - kernel_thread.SetName("BootZ: Kernel."); + if (reader_kernel.Blob()) { + auto kernel_thread = Boot::BootThread(reader_kernel.Blob()); + kernel_thread.SetName("BootZ: Kernel."); - handover_hdr->f_KernelImage = reader_kernel.Blob(); - handover_hdr->f_KernelSz = reader_kernel.Size(); + handover_hdr->f_KernelImage = reader_kernel.Blob(); + handover_hdr->f_KernelSz = reader_kernel.Size(); - Boot::ExitBootServices(map_key, image_handle); + Boot::ExitBootServices(map_key, image_handle); - kernel_thread.Start(handover_hdr, YES); - } + kernel_thread.Start(handover_hdr, YES); + } - CANT_REACH(); + CANT_REACH(); } diff --git a/dev/boot/src/HEL/ARM64/BootPlatform.cc b/dev/boot/src/HEL/ARM64/BootPlatform.cc index bf359c6c..0f6a738f 100644 --- a/dev/boot/src/HEL/ARM64/BootPlatform.cc +++ b/dev/boot/src/HEL/ARM64/BootPlatform.cc @@ -1,37 +1,27 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ +#include <BootKit/BootKit.h> #include <BootKit/Platform.h> #include <BootKit/Protocol.h> -#include <BootKit/BootKit.h> #ifdef __BOOTZ_STANDALONE__ using namespace Boot; -EXTERN_C void rt_hlt() -{ - while (Yes) - ; +EXTERN_C void rt_hlt() { + while (Yes); } -EXTERN_C void rt_cli() -{ -} +EXTERN_C void rt_cli() {} -EXTERN_C void rt_sti() -{ -} +EXTERN_C void rt_sti() {} -EXTERN_C void rt_cld() -{ -} +EXTERN_C void rt_cld() {} -EXTERN_C void rt_std() -{ -} +EXTERN_C void rt_std() {} -#endif // __BOOTZ_STANDALONE__ +#endif // __BOOTZ_STANDALONE__ diff --git a/dev/boot/src/New+Delete.cc b/dev/boot/src/New+Delete.cc index 387ceaa0..f7ad2898 100644 --- a/dev/boot/src/New+Delete.cc +++ b/dev/boot/src/New+Delete.cc @@ -1,12 +1,12 @@ /* ------------------------------------------- - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ +#include <BootKit/BootKit.h> #include <BootKit/Platform.h> #include <BootKit/Protocol.h> -#include <BootKit/BootKit.h> #include <FirmwareKit/EFI/API.h> #ifdef __BOOTZ_STANDALONE__ @@ -14,71 +14,60 @@ /// @brief Allocates a new object. /// @param sz the size. /// @return -void* operator new(size_t sz) -{ - void* buf = nullptr; +void* operator new(size_t sz) { + void* buf = nullptr; - while (BS->AllocatePool(EfiMemoryType::EfiLoaderData, sz, &buf) != kEfiOk) - ; + while (BS->AllocatePool(EfiMemoryType::EfiLoaderData, sz, &buf) != kEfiOk); - return buf; + return buf; } /// @brief Allocates a new object. /// @param sz the size. /// @return -void* operator new[](size_t sz) -{ - void* buf = nullptr; - BS->AllocatePool(EfiMemoryType::EfiLoaderData, sz, &buf); +void* operator new[](size_t sz) { + void* buf = nullptr; + BS->AllocatePool(EfiMemoryType::EfiLoaderData, sz, &buf); - return buf; + return buf; } /// @brief Deletes the object. /// @param buf the object. -void operator delete(void* buf) -{ - if (!buf) - return; +void operator delete(void* buf) { + if (!buf) return; - BS->FreePool(buf); + BS->FreePool(buf); } /// @brief Deletes the object. /// @param buf the object. -void operator delete[](void* buf) -{ - if (!buf) - return; +void operator delete[](void* buf) { + if (!buf) return; - BS->FreePool(buf); + BS->FreePool(buf); } /// @brief Deletes the object (array specific). /// @param buf the object. /// @param size it's size. -void operator delete(void* buf, size_t size) -{ - if (!buf) - return; +void operator delete(void* buf, size_t size) { + if (!buf) return; - NE_UNUSED(size); + NE_UNUSED(size); - BS->FreePool(buf); + BS->FreePool(buf); } /// @brief Deletes the object (array specific). /// @param buf the object. /// @param size it's size. -void operator delete[](void* buf, size_t size) -{ - if (!buf) - return; +void operator delete[](void* buf, size_t size) { + if (!buf) return; - NE_UNUSED(size); + NE_UNUSED(size); - BS->FreePool(buf); + BS->FreePool(buf); } -#endif // __BOOTZ_STANDALONE__ +#endif // __BOOTZ_STANDALONE__ |
