summaryrefslogtreecommitdiffhomepage
path: root/Private/NewBoot/BootKit/BootKit.hxx
diff options
context:
space:
mode:
authorAmlal <amlalelmahrouss@icloud.com>2024-04-26 12:29:13 +0000
committerAmlal <amlalelmahrouss@icloud.com>2024-04-26 12:29:13 +0000
commit97eb8462433a831f8a02a08acfc7ca32e794d37d (patch)
treee7cddb857e50a2cca41a5364b4240cd8c6c0ec13 /Private/NewBoot/BootKit/BootKit.hxx
parentf7a7080d18ac2be758b242c22f020c018b1c4824 (diff)
parent313c303fab092b1c45e615f960826375e7eef093 (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.hxx274
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;
+}