summaryrefslogtreecommitdiffhomepage
path: root/tooling
diff options
context:
space:
mode:
authorAmlal <amlal@nekernel.org>2025-04-26 16:56:37 +0200
committerAmlal <amlal@nekernel.org>2025-04-26 17:15:56 +0200
commit360c69daf7a83ec31c384390d9ec37064b78b40e (patch)
treebf78f6267b032815f992f02768251186dbeda7d5 /tooling
parent9c33e844d76f9db6d7110de4f05cbe2084cdbca1 (diff)
dev, kernel, tooling: add HeFS tooling and early allocation stategy.
why? - we need to format it externally too. - a in-kernel format doesn't handle every case. - and i have to fix the createdir, createfile methods for correct inode dir linking. Signed-off-by: Amlal <amlal@nekernel.org>
Diffstat (limited to 'tooling')
-rw-r--r--tooling/dist/.keep0
-rw-r--r--tooling/hefs.h161
-rw-r--r--tooling/mkfs.hefs.cc165
-rw-r--r--tooling/mkfs.hefs.json16
4 files changed, 342 insertions, 0 deletions
diff --git a/tooling/dist/.keep b/tooling/dist/.keep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tooling/dist/.keep
diff --git a/tooling/hefs.h b/tooling/hefs.h
new file mode 100644
index 00000000..a85cb2bc
--- /dev/null
+++ b/tooling/hefs.h
@@ -0,0 +1,161 @@
+/* -------------------------------------------
+
+ Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <cstdint>
+#include <cstring>
+
+#define kHeFSVersion (0x0101)
+#define kHeFSMagic " HeFS"
+#define kHeFSMagicLen (8)
+
+#define kHeFSFileNameLen (256U)
+#define kHeFSPartNameLen (128U)
+
+#define kHeFSMinimumDiskSize (gib_cast(4))
+
+#define kHeFSDefaultVoluneName u"HeFS Volume"
+
+#define kHeFSDIMBootDir u"boot-x/dir"
+#define kHeFSMIMEBootFile u"boot-x/file"
+
+#define kHeFSDIMSystemDir u"system-x/dir"
+#define kHeFSMIMESystemFile u"system-x/file"
+
+#define kHeFSSearchAllStr u"*"
+
+namespace mkfs::hefs {
+enum {
+ kHeFSHardDrive = 0xC0, // Hard Drive
+ kHeFSSolidStateDrive = 0xC1, // Solid State Drive
+ kHeFSOpticalDrive = 0x0C, // Blu-Ray/DVD
+ kHeFSMassStorageDevice = 0xCC, // USB
+ kHeFSScsiDrive = 0xC4, // SCSI Hard Drive
+ kHeFSFlashDrive = 0xC6,
+ kHeFSUnknown = 0xFF, // Unknown device.
+ kHeFSDriveCount = 7,
+};
+
+enum {
+ kHeFSStatusUnlocked = 0x18,
+ kHeFSStatusLocked,
+ kHeFSStatusError,
+ kHeFSStatusInvalid,
+ kHeFSStatusCount,
+};
+
+enum {
+ kHeFSEncodingUTF8 = 0x00,
+ kHeFSEncodingUTF16,
+ kHeFSEncodingUTF32,
+ kHeFSEncodingUTF16BE,
+ kHeFSEncodingUTF16LE,
+ kHeFSEncodingUTF32BE,
+ kHeFSEncodingUTF32LE,
+ kHeFSEncodingUTF8BE,
+ kHeFSEncodingUTF8LE,
+ kHeFSEncodingBinary,
+ kHeFSEncodingCount,
+};
+
+// Constants
+constexpr std::size_t kHeFSBlockCount = 16;
+
+// Types
+using ATime = std::uint64_t;
+
+inline constexpr uint16_t kHeFSFileKindRegular = 0x00;
+inline constexpr uint16_t kHeFSFileKindDirectory = 0x01;
+inline constexpr uint16_t kHeFSFileKindBlock = 0x02;
+inline constexpr uint16_t kHeFSFileKindCharacter = 0x03;
+inline constexpr uint16_t kHeFSFileKindFIFO = 0x04;
+inline constexpr uint16_t kHeFSFileKindSocket = 0x05;
+inline constexpr uint16_t kHeFSFileKindSymbolicLink = 0x06;
+inline constexpr uint16_t kHeFSFileKindUnknown = 0x07;
+inline constexpr uint16_t kHeFSFileKindCount = 0x08;
+
+// Basic Time Constants
+inline constexpr ATime kHeFSTimeInvalid = 0x0000000000000000;
+inline constexpr ATime kHeFSTimeMax = 0xFFFFFFFFFFFFFFFF - 1;
+
+// Boot Node (Superblock Equivalent)
+struct alignas(8) BootNode {
+ char magic[kHeFSMagicLen]{};
+ char16_t volumeName[kHeFSPartNameLen]{};
+ std::uint32_t version{};
+ std::uint64_t badSectors{};
+ std::uint64_t sectorCount{};
+ std::uint64_t sectorSize{};
+ std::uint32_t checksum{};
+ std::uint8_t diskKind{};
+ std::uint8_t encoding{};
+ std::uint64_t startIND{};
+ std::uint64_t endIND{};
+ std::uint64_t indCount{};
+ std::uint64_t diskSize{};
+ std::uint16_t diskStatus{};
+ std::uint16_t diskFlags{};
+ std::uint16_t vid{};
+ std::uint64_t reserved{};
+ std::uint64_t reserved2{};
+ std::uint64_t reserved3{};
+ std::uint64_t reserved4{};
+};
+
+// File Node (Index Node)
+struct alignas(8) IndexNode {
+ char16_t name[kHeFSFileNameLen]{};
+ std::uint32_t flags{};
+ std::uint16_t kind{};
+ std::uint32_t size{};
+ std::uint32_t checksum{};
+ std::uint32_t recoverChecksum{};
+ std::uint32_t blockChecksum{};
+ std::uint32_t linkChecksum{};
+ char16_t mime[kHeFSFileNameLen]{};
+ bool symbolicLink{false};
+ ATime created{};
+ ATime accessed{};
+ ATime modified{};
+ ATime deleted{};
+ std::uint32_t uid{};
+ std::uint32_t gid{};
+ std::uint32_t mode{};
+ std::uint64_t blockLinkStart[kHeFSBlockCount]{};
+ std::uint64_t blockLinkEnd[kHeFSBlockCount]{};
+ std::uint64_t blockStart[kHeFSBlockCount]{};
+ std::uint64_t blockEnd[kHeFSBlockCount]{};
+ std::uint64_t blockRecoveryStart[kHeFSBlockCount]{};
+ std::uint64_t blockRecoveryEnd[kHeFSBlockCount]{};
+};
+
+// Directory Node (Red-Black Tree Node)
+struct alignas(8) IndexNodeDirectory {
+ char16_t name[kHeFSFileNameLen]{};
+ std::uint32_t flags{};
+ std::uint16_t kind{};
+ std::uint32_t entryCount{};
+ std::uint32_t checksum{};
+ std::uint32_t indexNodeChecksum{};
+ char16_t dim[kHeFSFileNameLen]{};
+ ATime created{};
+ ATime accessed{};
+ ATime modified{};
+ ATime deleted{};
+ std::uint32_t uid{};
+ std::uint32_t gid{};
+ std::uint32_t mode{};
+ std::uint64_t indexNodeStart[kHeFSBlockCount]{};
+ std::uint64_t indexNodeEnd[kHeFSBlockCount]{};
+ std::uint8_t color{};
+ std::uint64_t next{};
+ std::uint64_t prev{};
+ std::uint64_t child{};
+ std::uint64_t parent{};
+};
+
+} // namespace mkfs::hefs
diff --git a/tooling/mkfs.hefs.cc b/tooling/mkfs.hefs.cc
new file mode 100644
index 00000000..15b18a8a
--- /dev/null
+++ b/tooling/mkfs.hefs.cc
@@ -0,0 +1,165 @@
+/* -------------------------------------------
+
+ Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#include <tooling/hefs.h>
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#include <string>
+
+/// @internal
+namespace detail {
+/// @brief Helper function to get the option value from command line arguments.
+template <typename CharType>
+static std::basic_string<CharType> get_option(const std::basic_string<CharType>& args,
+ const std::basic_string<CharType>& option) {
+ size_t pos = args.find(option + CharType('='));
+
+ if (pos != std::string::npos) {
+ size_t start = pos + option.length() + 1;
+ size_t end = args.find(' ', start);
+ return args.substr(start, end - start);
+ }
+
+ return std::basic_string<CharType>{};
+}
+} // namespace detail
+
+static size_t kDiskSize = 1024 * 1024 * 1024 * 4UL;
+static uint16_t kVersion = kHeFSVersion;
+static std::u16string kLabel = kHeFSDefaultVoluneName;
+static size_t kSectorSize = 512;
+
+int main(int argc, char** argv) {
+ if (argc < 2) {
+ std::cerr << "mkfs.hefs: Error: Missing required arguments." << std::endl;
+ std::cerr << "mkfs.hefs: Usage: mkfs.hefs -L <label> -s <sector_size> -p <part_start> -e "
+ "<part_end> -S <disk_size> -o <output_device>"
+ << std::endl;
+ return 1;
+ }
+
+ std::string args;
+ std::u16string args_wide;
+
+ for (int i = 1; i < argc; ++i) {
+ args += argv[i];
+ args += " ";
+
+
+ std::string str = argv[i];
+
+ for (auto& ch : str)
+ {
+ args_wide.push_back(ch);
+ }
+
+ args_wide += u" ";
+ }
+
+ auto output_device = detail::get_option<char>(args, "-o");
+
+ kSectorSize = std::strtol(detail::get_option<char>(args, "-s").data(), nullptr, 10);
+ kLabel = detail::get_option<char16_t>(args_wide, u"-L");
+
+ if (kLabel.empty())
+ kLabel = kHeFSDefaultVoluneName;
+
+ kDiskSize =
+ std::strtol(detail::get_option<char>(args, "-S").data(), nullptr, 10) * 1024 * 1024 * 1024;
+
+ if (kDiskSize == 0) {
+ std::cerr << "mkfs.hefs: Error: Invalid size specified." << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ // Open the output_device
+ std::ofstream filesystem(output_device, std::ios::binary);
+
+ if (!filesystem.good()) {
+ std::cerr << "mkfs.hefs: Error: Unable to open output_device " << output_device << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ // create a boot node, and then allocate a index node directory tree.
+ mkfs::hefs::BootNode bootNode{{}, {}, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ auto start_ind = std::strtol(detail::get_option<char>(args, "-p").data(), nullptr, 10);
+ start_ind += sizeof(mkfs::hefs::BootNode);
+
+ auto end_ind = std::strtol(detail::get_option<char>(args, "-e").data(), nullptr, 10);
+
+ bootNode.version = kVersion;
+ bootNode.diskKind = mkfs::hefs::kHeFSHardDrive;
+ bootNode.encoding = mkfs::hefs::kHeFSEncodingUTF16;
+ bootNode.diskSize = kDiskSize;
+ bootNode.sectorSize = kSectorSize;
+ bootNode.startIND = start_ind;
+ bootNode.endIND = end_ind;
+ bootNode.diskStatus = mkfs::hefs::kHeFSStatusUnlocked;
+
+ std::memcpy(bootNode.magic, kHeFSMagic, kHeFSMagicLen);
+ std::memcpy(bootNode.volumeName, kLabel.data(), kLabel.size() * sizeof(char16_t));
+
+ filesystem.seekp(std::strtol(detail::get_option<char>(args, "-p").data(), nullptr, 10));
+ filesystem.write(reinterpret_cast<const char*>(&bootNode), sizeof(mkfs::hefs::BootNode));
+
+ if (!filesystem.good()) {
+ std::cerr << "mkfs.hefs: Error: Unable to write to output_device " << output_device
+ << std::endl;
+ return 1;
+ }
+
+ filesystem.seekp(bootNode.startIND);
+
+ auto cnt = end_ind / sizeof(mkfs::hefs::IndexNodeDirectory);
+
+ // Pre-allocate index node directory tree
+ for (size_t i = 0; i < cnt; ++i) {
+ mkfs::hefs::IndexNodeDirectory indexNode{};
+
+ std::memcpy(indexNode.name, u"$UNALLOCATED$", std::u16string(u"$UNALLOCATED$").size() * sizeof(char16_t));
+
+ indexNode.flags = 0;
+ indexNode.kind = mkfs::hefs::kHeFSFileKindDirectory;
+ indexNode.deleted = mkfs::hefs::kHeFSTimeMax;
+
+ indexNode.entryCount = 1;
+
+ indexNode.checksum = 0;
+ indexNode.indexNodeChecksum = 0;
+
+ indexNode.uid = 0;
+ indexNode.gid = 0;
+ indexNode.mode = 0;
+ indexNode.color = 0;
+ indexNode.next = 0;
+ indexNode.prev = 0;
+ indexNode.child = 0;
+
+ indexNode.parent = bootNode.startIND;
+ indexNode.child = bootNode.endIND;
+
+ indexNode.next = 0;
+ indexNode.prev = 0;
+
+ filesystem.write(reinterpret_cast<const char*>(&indexNode),
+ sizeof(mkfs::hefs::IndexNodeDirectory));
+
+ if (!filesystem.good()) {
+ std::cerr << "mkfs.hefs: Error: Unable to write index node to output_device " << output_device
+ << std::endl;
+ return 1;
+ }
+ }
+
+ filesystem.flush();
+ filesystem.close();
+
+ std::cout << "mkfs.hefs: HeFS filesystem created on " << output_device << std::endl;
+
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/tooling/mkfs.hefs.json b/tooling/mkfs.hefs.json
new file mode 100644
index 00000000..d29b7f73
--- /dev/null
+++ b/tooling/mkfs.hefs.json
@@ -0,0 +1,16 @@
+{
+ "compiler_path": "g++",
+ "compiler_std": "c++20",
+ "headers_path": [
+ "../"
+ ],
+ "sources_path": [
+ "mkfs.hefs.cc"
+ ],
+ "output_name": "./dist/mkfs.hefs",
+ "cpp_macros": [
+ "kMKFSHEFSVersion=0x0100",
+ "kMKFSHEFSVersionHighest=0x0100",
+ "kMKFSHEFSVersionLowest=0x0100"
+ ]
+} \ No newline at end of file