diff options
| author | Amlal <amlalelmahrouss@icloud.com> | 2024-04-26 12:29:13 +0000 |
|---|---|---|
| committer | Amlal <amlalelmahrouss@icloud.com> | 2024-04-26 12:29:13 +0000 |
| commit | 97eb8462433a831f8a02a08acfc7ca32e794d37d (patch) | |
| tree | e7cddb857e50a2cca41a5364b4240cd8c6c0ec13 /Private/NewBoot/BootKit/BootKit.hxx | |
| parent | f7a7080d18ac2be758b242c22f020c018b1c4824 (diff) | |
| parent | 313c303fab092b1c45e615f960826375e7eef093 (diff) | |
Merged in MHR-16 (pull request #6)
MHR-16 - A lot of features and USA design.
Diffstat (limited to 'Private/NewBoot/BootKit/BootKit.hxx')
| -rw-r--r-- | Private/NewBoot/BootKit/BootKit.hxx | 274 |
1 files changed, 246 insertions, 28 deletions
diff --git a/Private/NewBoot/BootKit/BootKit.hxx b/Private/NewBoot/BootKit/BootKit.hxx index 1a992166..f7f33958 100644 --- a/Private/NewBoot/BootKit/BootKit.hxx +++ b/Private/NewBoot/BootKit/BootKit.hxx @@ -6,11 +6,27 @@ /***********************************************************************************/ /// @file Boot.hxx -/// @brief Bootloader API. +/// @brief Bootloader Programming Interface. /***********************************************************************************/ #pragma once +#include <BootKit/HW/ATA.hxx> +#include <CompilerKit/Version.hxx> + +/// include NewFS header and Support header as well. + +#include <FSKit/NewFS.hxx> +#include <cstring> +#include <BootKit/Vendor/Support.hxx> + +/***********************************************************************************/ +/// Include other APIs. +/***********************************************************************************/ + +#include <NewKit/Defines.hpp> +#include <Builtins/ATA/ATA.hxx> + /***********************************************************************************/ /// Framebuffer helpers. /***********************************************************************************/ @@ -22,40 +38,22 @@ class BFileReader; class BFileRunner; class BVersionString; -#include <BootKit/HW/ATA.hxx> -#include <CompilerKit/Version.hxx> - -/***********************************************************************************/ -/// Include other APIs. -/***********************************************************************************/ - -#include <BootKit/Platform.hxx> -#include <BootKit/Protocol.hxx> - ///! @note This address is reserved to NewKernel. #define kBootVirtualAddress (0xfffffff80000000) -#ifdef __EFI_x86_64__ -#include <FirmwareKit/EFI.hxx> -#endif // ifdef __EFI_x86_64__ - -#include <FirmwareKit/EPM.hxx> -#include <NewKit/Defines.hpp> - using namespace NewOS; typedef Char *PEFImagePtr; typedef Char *PEImagePtr; -enum { - kSegmentCode = 2, - kSegmentData = 4, - kSegmentBss = 6, -}; - typedef WideChar CharacterTypeUTF16; typedef Char CharacterTypeUTF8; +namespace EFI { + extern void ThrowError(const CharacterTypeUTF16 *ErrorCode, + const CharacterTypeUTF16 *Reason) noexcept; +} + /** * @brief BootKit Text Writer class * Writes to UEFI StdOut. @@ -65,7 +63,7 @@ class BTextWriter final { public: BTextWriter &Write(const Long &num); - BTextWriter &Write(const UChar *str); + BTextWriter &Write(const Char *str); BTextWriter &Write(const CharacterTypeUTF16 *str); BTextWriter &WriteCharacter(CharacterTypeUTF16 c); @@ -147,9 +145,6 @@ class BVersionString final { static const CharacterTypeUTF16 *Shared() { return BOOTLOADER_VERSION; } }; -/// @brief Bootloader main type. -typedef void (*BootMainKind)(HEL::HandoverInformationHeader *handoverInfo); - /***********************************************************************************/ /// Provide some useful processor features. /***********************************************************************************/ @@ -180,3 +175,226 @@ static inline const UInt32 kRgbGreen = 0x0000FF00; static inline const UInt32 kRgbBlue = 0x00FF0000; static inline const UInt32 kRgbBlack = 0x00000000; static inline const UInt32 kRgbWhite = 0x00FFFFFF; + +#define kBKBootFileMime "boot-x/file" +#define kBKBootDirMime "boot-x/dir" + +/// @brief BootKit Disk Formatter. +template <typename BootDev> +class BDiskFormatFactory final { +public: + /// @brief File entry for **BDiskFormatFactory**. + struct BFileDescriptor final { + Char fFileName[kNewFSNodeNameLen]; + Char fForkName[kNewFSNodeNameLen]; + + UInt32 fKind; + + VoidPtr fBlob; + SizeT fBlobSz; + + struct BFileDescriptor* fPrev; + struct BFileDescriptor* fNext; + }; + +public: + explicit BDiskFormatFactory() = default; + explicit BDiskFormatFactory(BootDev dev) : fDiskDev(dev) {} + + ~BDiskFormatFactory() = default; + + NEWOS_COPY_DELETE(BDiskFormatFactory); + + /// @brief Format disk. + /// @param Partition Name + /// @param Blobs. + /// @param Number of blobs. + /// @retval True disk has been formatted. + /// @retval False failed to format. + Boolean Format(const char* partName, BFileDescriptor* fileBlobs, SizeT blobCount); + + /// @brief check if partition is good. + operator bool() noexcept { + fDiskDev.Leak().mBase = (kNewFSAddressAsLba); + fDiskDev.Leak().mSize = BootDev::kSectorSize; + + Char buf[BootDev::kSectorSize] = { 0 }; + + fDiskDev.Read(buf, BootDev::kSectorSize); + + NewPartitionBlock* blockPart = reinterpret_cast<NewPartitionBlock*>(buf); + + for (SizeT indexMag = 0UL; indexMag < kNewFSIdentLen; ++indexMag) { + if (blockPart->Ident[indexMag] != kNewFSIdent[indexMag]) + return false; + } + + BTextWriter writer; + writer.Write(L"Device Size: ").Write(this->fDiskDev.GetDiskSize()).Write(L"\r\n"); + + if (blockPart->DiskSize != this->fDiskDev.GetDiskSize() || + blockPart->DiskSize < 1 || + blockPart->SectorSize != BootDev::kSectorSize) { + EFI::ThrowError(L"Invalid-Disk-Geometry", L"Invalid disk geometry."); + } else if (blockPart->PartitionName[0] == 0) { + EFI::ThrowError(L"Invalid-Partition-Name", L"Invalid disk partition."); + } + + writer.Write(L"Device Partition: ").Write(blockPart->PartitionName).Write(L" is healthy.\r\n"); + + return true; + } + +private: + /// @brief Write all of the requested catalogs into the filesystem. + Boolean WriteContent(BFileDescriptor* fileBlobs, SizeT blobCount, + SizeT sectorSz, NewPartitionBlock& partBlock) { + if (sectorSz != BootDev::kSectorSize) return false; + + BFileDescriptor* blob = fileBlobs; + Lba startLba = partBlock.StartCatalog; + BTextWriter writer; + + while (blob) { + NewCatalog* catalogKind = new NewCatalog(); + memset(catalogKind, 0, sizeof(NewCatalog)); + + /// Fill catalog kind. + catalogKind->Kind = blob->fKind; + + /// Allocate fork for blob. + catalogKind->FirstFork = (startLba + sizeof(NewCatalog)); + catalogKind->LastFork = catalogKind->FirstFork; + + NewFork* forkKind = new NewFork(); + memset(forkKind, 0, sizeof(NewFork)); + + memcpy(forkKind->Name, blob->fForkName, strlen(blob->fForkName)); + forkKind->Kind = (forkKind->Name[0] == kNewFSDataFork[0]) ? kNewFSDataForkKind : kNewFSRsrcForkKind; + forkKind->Flags = kNewFSFlagCreated; + + /// We don't know. + forkKind->ResourceFlags = 0; + forkKind->ResourceId = 0; + forkKind->ResourceKind = 0; + + /// We're the only fork here. + forkKind->NextSibling = catalogKind->FirstFork; + forkKind->PreviousSibling = catalogKind->FirstFork; + + forkKind->DataOffset = (startLba + sizeof(NewCatalog) + sizeof(NewFork)); + forkKind->DataSize = blob->fBlobSz; + + SizeT cur = 0UL; + + writer.Write((catalogKind->Kind == kNewFSCatalogKindFile) ? L"New Boot: Write-File: " : + L"New Boot: Write-Directory: " ).Write(blob->fFileName).Write(L"\r\n"); + + /// Set disk cursor here. + + fDiskDev.Leak().mBase = startLba + sizeof(NewCatalog); + fDiskDev.Leak().mSize = sizeof(NewFork); + + fDiskDev.Write((Char*)forkKind, sizeof(NewFork)); + + do { + this->fDiskDev.Leak().mSize = BootDev::kSectorSize; + this->fDiskDev.Leak().mBase = (forkKind->DataOffset + cur); + + this->fDiskDev.Write((Char*)(blob->fBlob) + cur, BootDev::kSectorSize); + + cur += BootDev::kSectorSize; + } while (cur < forkKind->DataSize); + + /// Fork is done. + + catalogKind->Kind = blob->fKind; + catalogKind->Flags |= kNewFSFlagCreated; + + Lba catalogLba = (sizeof(NewCatalog) - startLba); + + //// Now write catalog as well.. + + catalogKind->PrevSibling = startLba; + catalogKind->NextSibling = (sizeof(NewCatalog) + blob->fBlobSz); + + /// this mime only applies to file. + if (catalogKind->Kind == kNewFSCatalogKindFile) { + memcpy(catalogKind->Mime, kBKBootFileMime, strlen(kBKBootFileMime)); + } else { + memcpy(catalogKind->Mime, kBKBootDirMime, strlen(kBKBootDirMime)); + } + + memcpy(catalogKind->Name, blob->fFileName, strlen(blob->fFileName)); + + fDiskDev.Leak().mBase = startLba; + fDiskDev.Leak().mSize = sizeof(NewCatalog); + + fDiskDev.Write((Char*)catalogKind, sizeof(NewCatalog)); + + startLba += (sizeof(NewCatalog) + sizeof(NewFork) + blob->fBlobSz); + + --partBlock.FreeCatalog; + --partBlock.FreeSectors; + + delete forkKind; + delete catalogKind; + + blob = blob->fNext; + } + + return true; + } + +private: + BootDev fDiskDev; + +}; + +/// @brief Format disk. +/// @param Partition Name +/// @param Blobs. +/// @param Number of blobs. +/// @retval True disk has been formatted. +/// @retval False failed to format. +template <typename BootDev> +inline Boolean BDiskFormatFactory<BootDev>::Format(const char* partName, + BDiskFormatFactory::BFileDescriptor* fileBlobs, SizeT blobCount) { + if (!fileBlobs || !blobCount) return false; /// sanity check + + /// convert the sector into something that the disk understands. + SizeT sectorSz = BootDev::kSectorSize; + Char buf[BootDev::kSectorSize] = { 0 }; + + NewPartitionBlock* partBlock = reinterpret_cast<NewPartitionBlock*>(buf); + + memcpy(partBlock->Ident, kNewFSIdent, kNewFSIdentLen - 1); + memcpy(partBlock->PartitionName, partName, strlen(partName)); + + /// @note A catalog roughly equal to a sector. + + partBlock->CatalogCount = blobCount; + partBlock->Kind = kNewFSHardDrive; + partBlock->SectorSize = sectorSz; + partBlock->FreeCatalog = fDiskDev.GetSectorsCount() - partBlock->CatalogCount; + partBlock->SectorCount = fDiskDev.GetSectorsCount(); + partBlock->FreeSectors = fDiskDev.GetSectorsCount() - partBlock->CatalogCount; + partBlock->StartCatalog = kNewFSCatalogStartAddress; + partBlock->DiskSize = fDiskDev.GetDiskSize(); + + if (this->WriteContent(fileBlobs, blobCount, sectorSz, *partBlock)) { + fDiskDev.Leak().mBase = (kNewFSAddressAsLba); + fDiskDev.Leak().mSize = sectorSz; + + fDiskDev.Write(buf, sectorSz); + + BTextWriter writer; + writer.Write(L"New Boot: Write-Partition, OK.\r\n"); + + return true; + } else { + EFI::ThrowError(L"Filesystem-Failure-Part", L"Filesystem couldn't be partitioned."); + } + + return false; +} |
