summaryrefslogtreecommitdiffhomepage
path: root/dev
diff options
context:
space:
mode:
Diffstat (limited to 'dev')
-rw-r--r--dev/boot/BootKit/Device.h4
-rw-r--r--dev/boot/BootKit/HW/SATA.h6
-rw-r--r--dev/boot/amd64-ci.make4
-rw-r--r--dev/boot/amd64-desktop.make4
-rw-r--r--dev/boot/modules/BootNet/BootNet.cc9
-rw-r--r--dev/boot/modules/BootNet/amd64.json2
-rw-r--r--dev/boot/src/BootThread.cc25
-rw-r--r--dev/boot/src/HEL/AMD64/BootATA.cc13
-rw-r--r--dev/boot/src/HEL/AMD64/BootEFI.cc20
-rw-r--r--dev/boot/src/HEL/ARM64/BootAPI.S6
-rw-r--r--dev/boot/src/HEL/ARM64/BootCB.S4
-rw-r--r--dev/boot/src/HEL/ARM64/BootEFI.cc110
-rw-r--r--dev/boot/src/HEL/POWER/BootCB.S2
-rw-r--r--dev/boot/src/boot_rsrc.rsrc (renamed from dev/boot/src/BootloaderRsrc.rsrc)2
-rw-r--r--dev/kernel/ArchKit/ArchKit.h2
-rw-r--r--dev/kernel/CFKit/Utils.h4
-rw-r--r--dev/kernel/DmaKit/DmaPool.h25
-rw-r--r--dev/kernel/FSKit/HeFS.h4
-rw-r--r--dev/kernel/FirmwareKit/CoreBoot/BootNet.h14
-rw-r--r--dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc2
-rw-r--r--dev/kernel/HALKit/AMD64/HalCoreInterruptHandler.cc35
-rw-r--r--dev/kernel/HALKit/ARM64/APM/APM+IO.cc4
-rw-r--r--dev/kernel/HALKit/ARM64/HalACPIFactoryInterface.cc4
-rw-r--r--dev/kernel/HALKit/ARM64/HalCoreInterruptHandler.cc161
-rw-r--r--dev/kernel/HALKit/ARM64/HalHandoverStub.s15
-rw-r--r--dev/kernel/HALKit/ARM64/HalKernelPanic.cc4
-rw-r--r--dev/kernel/KernelKit/PCI/IO.h4
-rw-r--r--dev/kernel/KernelKit/PE.h3
-rw-r--r--dev/kernel/KernelKit/ThreadLocalStorage.h4
-rw-r--r--dev/kernel/KernelKit/UserMgr.h3
-rw-r--r--dev/kernel/KernelKit/UserProcessScheduler.h2
-rw-r--r--dev/kernel/NeKit/Utils.h4
-rw-r--r--dev/kernel/NetworkKit/IP.h16
-rw-r--r--dev/kernel/SwapKit/DiskSwap.h12
-rw-r--r--dev/kernel/kernel_rsrc.rsrc4
-rw-r--r--dev/kernel/src/AsciiUtils.cc (renamed from dev/kernel/src/Utils.cc)55
-rw-r--r--dev/kernel/src/CxxAbi-AMD64.cc9
-rw-r--r--dev/kernel/src/CxxAbi-ARM64.cc2
-rw-r--r--dev/kernel/src/FS/HeFS+FileSystemParser.cc11
-rw-r--r--dev/kernel/src/FS/NeFS+FileMgr.cc214
-rw-r--r--dev/kernel/src/FS/NeFS+FileSystemParser.cc751
-rw-r--r--dev/kernel/src/Network/IPAddr.cc34
-rw-r--r--dev/kernel/src/ThreadLocalStorage.cc22
-rw-r--r--dev/kernel/src/UserProcessScheduler.cc58
-rw-r--r--dev/libSystem/SystemKit/System.h10
-rw-r--r--dev/libSystem/libSystem.json2
-rw-r--r--dev/libSystem/src/Makefile2
-rw-r--r--dev/libSystem/src/SystemAPI.cc (renamed from dev/libSystem/src/SystemImpl.cc)0
-rw-r--r--dev/modules/APM/APM.h8
-rw-r--r--dev/open_msg/script/window.msg6
-rw-r--r--dev/open_msg/script/window_client.json7
51 files changed, 967 insertions, 761 deletions
diff --git a/dev/boot/BootKit/Device.h b/dev/boot/BootKit/Device.h
index 8f5bf854..6ae8cd6b 100644
--- a/dev/boot/BootKit/Device.h
+++ b/dev/boot/BootKit/Device.h
@@ -20,8 +20,8 @@ class Device {
NE_MOVE_DEFAULT(Device)
struct Trait {
- SizeT mBase{1024};
- SizeT mSize{1024};
+ SizeT mBase{0};
+ SizeT mSize{0};
};
virtual Trait& Leak() = 0;
diff --git a/dev/boot/BootKit/HW/SATA.h b/dev/boot/BootKit/HW/SATA.h
index eecf426d..d880c3af 100644
--- a/dev/boot/BootKit/HW/SATA.h
+++ b/dev/boot/BootKit/HW/SATA.h
@@ -10,7 +10,7 @@
#include <CompilerKit/CompilerKit.h>
#include <modules/AHCI/AHCI.h>
-#define kAHCISectorSz (4096)
+#define kAHCISectorSz (512)
class BootDeviceSATA final {
public:
@@ -19,11 +19,9 @@ class BootDeviceSATA final {
NE_COPY_DEFAULT(BootDeviceSATA)
- struct SATATrait final {
- Kernel::SizeT mBase{1024};
+ struct SATATrait final : public Device::Trait {
Kernel::Boolean mErr{false};
Kernel::Boolean mDetected{false};
- Kernel::SizeT mSize{0};
operator bool() { return !this->mErr; }
};
diff --git a/dev/boot/amd64-ci.make b/dev/boot/amd64-ci.make
index 0715151c..12e6407b 100644
--- a/dev/boot/amd64-ci.make
+++ b/dev/boot/amd64-ci.make
@@ -73,7 +73,7 @@ BOOTLOADER=ne_bootz
KERNEL=ne_kernel
SYSCHK=chk.efi
BOOTNET=net.efi
-SCIKIT=libSystem.sys
+SCIKIT=libSystem.dll
.PHONY: invalid-recipe
invalid-recipe:
@@ -98,7 +98,7 @@ endif
.PHONY: compile-amd64
compile-amd64:
- $(WINDRES) src/BootloaderRsrc.rsrc -O coff -o BootloaderRsrc.o
+ $(WINDRES) src/boot_rsrc.rsrc -O coff -o boot_rsrc.o
$(CC_GNU) $(NE_MODEL) $(STANDALONE_MACRO) $(FLAG_GNU) $(DEBUG) \
$(wildcard src/HEL/AMD64/*.cc) \
$(wildcard src/HEL/AMD64/*.S) \
diff --git a/dev/boot/amd64-desktop.make b/dev/boot/amd64-desktop.make
index d7515367..4b6a879c 100644
--- a/dev/boot/amd64-desktop.make
+++ b/dev/boot/amd64-desktop.make
@@ -75,7 +75,7 @@ BOOTLOADER=ne_bootz
KERNEL=ne_kernel
SYSCHK=chk.efi
BOOTNET=net.efi
-SCIKIT=libSystem.sys
+SCIKIT=libSystem.dll
DDK=ddk.sys
.PHONY: invalid-recipe
@@ -108,7 +108,7 @@ endif
.PHONY: compile-amd64
compile-amd64:
- $(WINDRES) src/BootloaderRsrc.rsrc -O coff -o BootloaderRsrc.o
+ $(WINDRES) src/boot_rsrc.rsrc -O coff -o boot_rsrc.o
$(CC_GNU) $(NE_MODEL) $(STANDALONE_MACRO) $(FLAG_GNU) $(DEBUG) \
$(wildcard src/HEL/AMD64/*.cc) \
$(wildcard src/HEL/AMD64/*.S) \
diff --git a/dev/boot/modules/BootNet/BootNet.cc b/dev/boot/modules/BootNet/BootNet.cc
index ba9beef4..8236dd0d 100644
--- a/dev/boot/modules/BootNet/BootNet.cc
+++ b/dev/boot/modules/BootNet/BootNet.cc
@@ -44,11 +44,16 @@ EXTERN_C Int32 BootNetModuleMain(Kernel::HEL::BootInfoHeader* handover) {
return kEfiFail;
}
+ if (inet_out->Version != kBootNetVersion) {
+ writer.Write("BootNet: The version clashes, not good.\r");
+ return kEfiFail;
+ }
+
if (!inet_out->ImpliesProgram) {
Boot::BootThread thread(inet_out->Data);
if (thread.IsValid()) {
- writer.Write("BootNet: Running kernel...\r");
+ writer.Write("BootNet: Running NeKernel...\r");
return thread.Start(handover, YES);
}
@@ -57,7 +62,7 @@ EXTERN_C Int32 BootNetModuleMain(Kernel::HEL::BootInfoHeader* handover) {
constexpr auto kROMSize = 0x200;
if (inet_out->Length > kROMSize) {
- writer.Write("BootNet: Not within 512K.\r");
+ writer.Write("BootNet: Not within 512K, won't flash EEPROM.\r");
return kEfiFail;
}
diff --git a/dev/boot/modules/BootNet/amd64.json b/dev/boot/modules/BootNet/amd64.json
index 912eeb0b..3d58cbc1 100644
--- a/dev/boot/modules/BootNet/amd64.json
+++ b/dev/boot/modules/BootNet/amd64.json
@@ -18,6 +18,6 @@
"__NE_AMD64__",
"kBootNetVersionHighest=0x0100",
"kBootNetVersionLowest=0x0100",
- "kBootNetVersion=0x0100"
+ "kBootNetEFIVersion=0x0100"
]
}
diff --git a/dev/boot/src/BootThread.cc b/dev/boot/src/BootThread.cc
index b502b52e..c477d659 100644
--- a/dev/boot/src/BootThread.cc
+++ b/dev/boot/src/BootThread.cc
@@ -15,6 +15,8 @@
#include <KernelKit/PEF.h>
#include <modules/CoreGfx/TextGfx.h>
+#define kBootThreadSz mib_cast(16)
+
/// @brief External boot services symbol.
EXTERN EfiBootServices* BS;
@@ -67,11 +69,10 @@ BootThread::BootThread(VoidPtr blob) : fStartAddress(nullptr), fBlob(blob) {
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");
+ writer.Write("BootZ: Image-Base: ").Write(loadStartAddress).Write("\r");
- fStack = new UInt8[mib_cast(16)];
+ fStack = new UInt8[kBootThreadSz];
if (!fStack) {
writer.Write("BootZ: Unable to allocate stack.\r");
@@ -155,16 +156,16 @@ BootThread::BootThread(VoidPtr blob) : fStartAddress(nullptr), fBlob(blob) {
/// @note handover header has to be valid!
Int32 BootThread::Start(HEL::BootInfoHeader* handover, Bool own_stack) {
- fHandover = handover;
-
if (!fStartAddress) {
return kEfiFail;
}
- if (!fHandover) {
+ if (!handover) {
return kEfiFail;
}
+ fHandover = handover;
+
BootTextWriter writer;
writer.Write("BootZ: Starting: ").Write(fBlobName).Write("\r");
@@ -172,13 +173,13 @@ Int32 BootThread::Start(HEL::BootInfoHeader* handover, Bool own_stack) {
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");
+ writer.Write("BootZ: Stack address: ").Write((UIntPtr) &fStack[kBootThreadSz - 1]).Write("\r");
+ writer.Write("BootZ: Stack size: ").Write(kBootThreadSz).Write("\r");
- fHandover->f_StackTop = &fStack[mib_cast(16) - 1];
- fHandover->f_StackSz = mib_cast(16);
+ fHandover->f_StackTop = &fStack[kBootThreadSz - 1];
+ fHandover->f_StackSz = kBootThreadSz;
- auto ret = rt_jump_to_address(fStartAddress, fHandover, &fStack[mib_cast(16) - 1]);
+ auto ret = rt_jump_to_address(fStartAddress, fHandover, &fStack[kBootThreadSz - 1]);
// we don't need the stack anymore.
@@ -187,7 +188,7 @@ Int32 BootThread::Start(HEL::BootInfoHeader* handover, Bool own_stack) {
return ret;
} else {
- writer.Write("BootZ: Using Bootloader's stack.\r");
+ writer.Write("BootZ: Using the bootloader's stack.\r");
return reinterpret_cast<HEL::HandoverProc>(fStartAddress)(fHandover);
}
diff --git a/dev/boot/src/HEL/AMD64/BootATA.cc b/dev/boot/src/HEL/AMD64/BootATA.cc
index e5e0d8c2..25810222 100644
--- a/dev/boot/src/HEL/AMD64/BootATA.cc
+++ b/dev/boot/src/HEL/AMD64/BootATA.cc
@@ -88,7 +88,8 @@ ATAInit_Retry:
/// fetch serial info
/// model, speed, number of sectors...
- while (!(rt_in8(IO + ATA_REG_STATUS) & ATA_SR_DRQ));
+ while (!(rt_in8(IO + ATA_REG_STATUS) & ATA_SR_DRQ))
+ ;
for (SizeT indexData = 0ul; indexData < kATADataLen; ++indexData) {
kATAData[indexData] = rt_in16(IO + ATA_REG_DATA);
@@ -114,14 +115,15 @@ Void boot_ata_read(UInt64 Lba, UInt16 IO, UInt8 Master, CharacterTypeASCII* Buf,
rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + SectorSz) / SectorSz));
- rt_out8(IO + ATA_REG_LBA0, (Lba) & 0xFF);
+ 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);
- while (!(rt_in8(IO + ATA_REG_STATUS) & ATA_SR_DRQ));
+ while (!(rt_in8(IO + ATA_REG_STATUS) & ATA_SR_DRQ))
+ ;
for (SizeT IndexOff = 0; IndexOff < Size; IndexOff += 2) {
boot_ata_wait_io(IO);
@@ -147,14 +149,15 @@ Void boot_ata_write(UInt64 Lba, UInt16 IO, UInt8 Master, CharacterTypeASCII* Buf
rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + (SectorSz)) / SectorSz));
- rt_out8(IO + ATA_REG_LBA0, (Lba) & 0xFF);
+ 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);
- while (!(rt_in8(IO + ATA_REG_STATUS) & ATA_SR_DRQ));
+ while (!(rt_in8(IO + ATA_REG_STATUS) & ATA_SR_DRQ))
+ ;
for (SizeT IndexOff = 0; IndexOff < Size; IndexOff += 2) {
boot_ata_wait_io(IO);
diff --git a/dev/boot/src/HEL/AMD64/BootEFI.cc b/dev/boot/src/HEL/AMD64/BootEFI.cc
index 166e0169..24bee2dd 100644
--- a/dev/boot/src/HEL/AMD64/BootEFI.cc
+++ b/dev/boot/src/HEL/AMD64/BootEFI.cc
@@ -128,28 +128,28 @@ EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, EfiSystemTa
handover_hdr->f_BitMapStart = nullptr; /* Start of bitmap. */
handover_hdr->f_BitMapSize = kHandoverBitMapSz; /* Size of bitmap in bytes. */
- Int32 trials = 5 * 10000000;
+ kHandoverHeader->f_BitMapStart = nullptr; /* Start of bitmap. */
+ kHandoverHeader->f_BitMapSize = kHandoverBitMapSz; /* Size of bitmap in bytes. */
- writer.Write("BootZ: Welcome to BootZ.\r");
- writer.Write("BootZ: Allocating sufficient memory, trying 4GB...\r");
+ UInt16 trials = 5;
- while (BS->AllocatePool(EfiLoaderData, handover_hdr->f_BitMapSize,
- &handover_hdr->f_BitMapStart) != kEfiOk) {
+ while (BS->AllocatePool(EfiLoaderData, kHandoverHeader->f_BitMapSize,
+ &kHandoverHeader->f_BitMapStart) != kEfiOk) {
--trials;
if (!trials) {
writer.Write("BootZ: Unable to allocate sufficient memory, trying again with 2GB...\r");
- trials = 3 * 10000000;
+ trials = 3;
- handover_hdr->f_BitMapSize = kHandoverBitMapSz / 2; /* Size of bitmap in bytes. */
+ kHandoverHeader->f_BitMapSize = kHandoverBitMapSz / 2; /* Size of bitmap in bytes. */
- while (BS->AllocatePool(EfiLoaderData, handover_hdr->f_BitMapSize,
- &handover_hdr->f_BitMapStart) != kEfiOk) {
+ while (BS->AllocatePool(EfiLoaderData, kHandoverHeader->f_BitMapSize,
+ &kHandoverHeader->f_BitMapStart) != kEfiOk) {
--trials;
if (!trials) {
- writer.Write("BootZ: Unable to allocate sufficent memory, aborting...\r");
+ writer.Write("BootZ: Unable to allocate sufficient memory, aborting...\r");
Boot::Stop();
}
}
diff --git a/dev/boot/src/HEL/ARM64/BootAPI.S b/dev/boot/src/HEL/ARM64/BootAPI.S
index a60ad218..55183abf 100644
--- a/dev/boot/src/HEL/ARM64/BootAPI.S
+++ b/dev/boot/src/HEL/ARM64/BootAPI.S
@@ -6,7 +6,7 @@
@brief this function setups a stack and then jumps to
a function */
rt_jump_to_address:
- mov x19, x0
- mov sp, x2
- blr x19
+ mov sp, x1
+ br x0
+ ret
diff --git a/dev/boot/src/HEL/ARM64/BootCB.S b/dev/boot/src/HEL/ARM64/BootCB.S
index 0c12c6c7..3b0e1737 100644
--- a/dev/boot/src/HEL/ARM64/BootCB.S
+++ b/dev/boot/src/HEL/ARM64/BootCB.S
@@ -15,9 +15,9 @@ boot_hdr_mag:
.ascii "CB"
boot_hdr_name:
// it has to match ten bytes.
- .asciz "bootz\0\0"
+ .asciz "bootz\0\0\0"
boot_hdr_ver:
- .word 0x104
+ .word 0x101
boot_hdr_proc:
.long bootloader_start
diff --git a/dev/boot/src/HEL/ARM64/BootEFI.cc b/dev/boot/src/HEL/ARM64/BootEFI.cc
index 66f91352..467cae23 100644
--- a/dev/boot/src/HEL/ARM64/BootEFI.cc
+++ b/dev/boot/src/HEL/ARM64/BootEFI.cc
@@ -71,12 +71,10 @@ EXTERN EfiBootServices* BS;
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();
-
- UInt32 map_key = 0;
+ kHandoverHeader = new HEL::BootInfoHeader();
#ifdef ZBA_USE_FB
- if (!boot_init_fb()) return 1; ///! Init the GOP.
+ if (!boot_init_fb()) return kEfiFail; ///! Init the GOP.
for (SizeT index_vt = 0; index_vt < sys_table->NumberOfTableEntries; ++index_vt) {
Char* vendor_table =
@@ -86,7 +84,7 @@ EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, EfiSystemTa
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;
+ kHandoverHeader->f_HardwareTables.f_VendorPtr = (VoidPtr) vendor_table;
break;
}
}
@@ -95,12 +93,12 @@ EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, EfiSystemTa
// 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;
+ kHandoverHeader->f_GOP.f_The = kGop->Mode->FrameBufferBase;
+ kHandoverHeader->f_GOP.f_Width = kGop->Mode->Info->VerticalResolution;
+ kHandoverHeader->f_GOP.f_Height = kGop->Mode->Info->HorizontalResolution;
+ kHandoverHeader->f_GOP.f_PixelPerLine = kGop->Mode->Info->PixelsPerScanLine;
+ kHandoverHeader->f_GOP.f_PixelFormat = kGop->Mode->Info->PixelFormat;
+ kHandoverHeader->f_GOP.f_Size = kGop->Mode->FrameBufferSize;
#endif // ZBA_USE_FB
// ------------------------------------------- //
@@ -111,29 +109,16 @@ EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, EfiSystemTa
EfiMpServicesProtocol* mp = nullptr;
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;
-
- fb_init();
-
- 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);
-
- fb_clear();
+ kHandoverHeader->f_HardwareTables.f_MpPtr = reinterpret_cast<VoidPtr>(mp);
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;
+ kHandoverHeader->f_HardwareTables.f_MultiProcessingEnabled = cnt_enabled > 1;
} else {
- handover_hdr->f_HardwareTables.f_MultiProcessingEnabled = NO;
+ kHandoverHeader->f_HardwareTables.f_MultiProcessingEnabled = NO;
}
//-------------------------------------------------------------//
@@ -142,73 +127,52 @@ EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, EfiSystemTa
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;
+ kHandoverHeader->f_BitMapStart = nullptr; /* Start of bitmap. */
+ kHandoverHeader->f_BitMapSize = kHandoverBitMapSz; /* Size of bitmap in bytes. */
+
+ UInt16 trials = 5;
- while (BS->AllocatePool(EfiLoaderData, handover_hdr->f_BitMapSize,
- &handover_hdr->f_BitMapStart) != kEfiOk) {
+ while (BS->AllocatePool(EfiLoaderData, kHandoverHeader->f_BitMapSize,
+ &kHandoverHeader->f_BitMapStart) != kEfiOk) {
--trials;
if (!trials) {
- writer.Write("BootZ: Unable to allocate sufficent memory, trying again with 2GB...\r");
+ writer.Write("BootZ: Unable to allocate sufficient memory, trying again with 2GB...\r");
- trials = 3 * 10000000;
+ trials = 3;
- handover_hdr->f_BitMapSize = kHandoverBitMapSz / 2; /* Size of bitmap in bytes. */
+ kHandoverHeader->f_BitMapSize = kHandoverBitMapSz / 2; /* Size of bitmap in bytes. */
- while (BS->AllocatePool(EfiLoaderData, handover_hdr->f_BitMapSize,
- &handover_hdr->f_BitMapStart) != kEfiOk) {
+ while (BS->AllocatePool(EfiLoaderData, kHandoverHeader->f_BitMapSize,
+ &kHandoverHeader->f_BitMapStart) != kEfiOk) {
--trials;
if (!trials) {
- writer.Write("BootZ: Unable to allocate sufficent memory, aborting...\r");
+ writer.Write("BootZ: Unable to allocate sufficient memory, aborting...\r");
Boot::Stop();
}
}
}
}
- Boot::BootFileReader reader_syschk(L"chk.efi", image_handle);
- reader_syschk.ReadAll(0);
-
- Boot::BootThread* syschk_thread = nullptr;
-
- 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();
-
- 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);
-
- fb_clear();
- }
- }
-
// ------------------------------------------ //
// null these fields, to avoid being reused later.
// ------------------------------------------ //
- handover_hdr->f_FirmwareCustomTables[0] = nullptr;
- handover_hdr->f_FirmwareCustomTables[1] = nullptr;
+ kHandoverHeader->f_FirmwareCustomTables[0] = nullptr;
+ kHandoverHeader->f_FirmwareCustomTables[1] = nullptr;
- handover_hdr->f_FirmwareVendorLen = Boot::BStrLen(sys_table->FirmwareVendor);
+ kHandoverHeader->f_FirmwareVendorLen = Boot::BStrLen(sys_table->FirmwareVendor);
- handover_hdr->f_Magic = kHandoverMagic;
- handover_hdr->f_Version = kHandoverVersion;
+ kHandoverHeader->f_Magic = kHandoverMagic;
+ kHandoverHeader->f_Version = kHandoverVersion;
// Provide fimware vendor name.
- Boot::BCopyMem(handover_hdr->f_FirmwareVendorName, sys_table->FirmwareVendor,
- handover_hdr->f_FirmwareVendorLen);
+ Boot::BCopyMem(kHandoverHeader->f_FirmwareVendorName, sys_table->FirmwareVendor,
+ kHandoverHeader->f_FirmwareVendorLen);
- handover_hdr->f_FirmwareVendorLen = Boot::BStrLen(sys_table->FirmwareVendor);
+ kHandoverHeader->f_FirmwareVendorLen = Boot::BStrLen(sys_table->FirmwareVendor);
Boot::BootFileReader reader_kernel(L"ne_kernel", image_handle);
@@ -220,14 +184,12 @@ EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, EfiSystemTa
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();
+ kernel_thread.SetName("NeKernel");
- Boot::ExitBootServices(map_key, image_handle);
+ kHandoverHeader->f_KernelImage = reader_kernel.Blob();
+ kHandoverHeader->f_KernelSz = reader_kernel.Size();
- kernel_thread.Start(handover_hdr, YES);
+ kernel_thread.Start(kHandoverHeader, YES);
}
CANT_REACH();
diff --git a/dev/boot/src/HEL/POWER/BootCB.S b/dev/boot/src/HEL/POWER/BootCB.S
index dae28871..3887ff10 100644
--- a/dev/boot/src/HEL/POWER/BootCB.S
+++ b/dev/boot/src/HEL/POWER/BootCB.S
@@ -15,7 +15,7 @@ boot_hdr_name:
// it has to match ten bytes.
.asciz "bootz\0\0\0"
boot_hdr_ver:
- .word 0x104
+ .word 0x101
boot_hdr_proc:
.long bootloader_start
diff --git a/dev/boot/src/BootloaderRsrc.rsrc b/dev/boot/src/boot_rsrc.rsrc
index 33bce7f7..fedbdee0 100644
--- a/dev/boot/src/BootloaderRsrc.rsrc
+++ b/dev/boot/src/boot_rsrc.rsrc
@@ -12,7 +12,7 @@ BEGIN
VALUE "FileDescription", "NeKernel OS Loader."
VALUE "FileVersion", BOOTLOADER_VERSION
VALUE "InternalName", "bootz"
- VALUE "LegalCopyright", "Copyright (C) 2024, Amlal El Mahrouss all rights reserved."
+ VALUE "LegalCopyright", "Copyright (C) 2024-2025, Amlal El Mahrouss all rights reserved."
VALUE "OriginalFilename", "ne_bootz"
VALUE "ProductName", "bootz"
VALUE "ProductVersion", BOOTLOADER_VERSION
diff --git a/dev/kernel/ArchKit/ArchKit.h b/dev/kernel/ArchKit/ArchKit.h
index 09839d98..a9dca240 100644
--- a/dev/kernel/ArchKit/ArchKit.h
+++ b/dev/kernel/ArchKit/ArchKit.h
@@ -70,7 +70,7 @@ namespace HAL {
typedef Kernel::Void (*rt_syscall_proc)(Kernel::VoidPtr);
struct HAL_DISPATCH_ENTRY final {
- Kernel::Int64 fHash;
+ Kernel::UInt64 fHash;
Kernel::Bool fHooked;
rt_syscall_proc fProc;
diff --git a/dev/kernel/CFKit/Utils.h b/dev/kernel/CFKit/Utils.h
index a5df8097..97b0ee53 100644
--- a/dev/kernel/CFKit/Utils.h
+++ b/dev/kernel/CFKit/Utils.h
@@ -16,7 +16,11 @@ inline auto ldr_find_exec_header(DosHeaderPtr ptrDos) -> LDR_EXEC_HEADER_PTR {
if (ptrDos->eMagic[1] != kMagMz1) return nullptr;
+#ifdef __NE_AMD64__
return (LDR_EXEC_HEADER_PTR) (VoidPtr) (&ptrDos->eLfanew + 1);
+#else
+ return (LDR_EXEC_HEADER_PTR) (VoidPtr) (&ptrDos->eLfanew);
+#endif
}
/// @brief Finds the PE optional header inside the blob.
diff --git a/dev/kernel/DmaKit/DmaPool.h b/dev/kernel/DmaKit/DmaPool.h
index 9decb3f1..ada8299e 100644
--- a/dev/kernel/DmaKit/DmaPool.h
+++ b/dev/kernel/DmaKit/DmaPool.h
@@ -2,19 +2,28 @@
Copyright (C) 2025, Amlal El Mahrouss , all rights reserved.
- File: FileMgr.h
- Purpose: Kernel file manager.
+ File: DmaPool.h
+ Purpose: Dma Pool Manager.
------------------------------------------- */
#pragma once
-#include <HALKit/AMD64/Processor.h>
#include <KernelKit/DebugOutput.h>
#ifdef __NE_AMD64__
+#include <HALKit/AMD64/Processor.h>
+#define kNeDMAPoolStart (0x1000000)
+#define kNeDMAPoolSize (0x1000000)
+#elif defined(__NE_ARM64__)
+#include <HALKit/ARM64/Processor.h>
+
+/// @todo what reference offset shall we use?
#define kNeDMAPoolStart (0x1000000)
#define kNeDMAPoolSize (0x1000000)
+#endif
+
+#define kNeDMABestAlign __BIGGEST_ALIGNMENT__
namespace Kernel {
/// @brief DMA pool base pointer, here we're sure that AHCI or whatever tricky standard sees it.
@@ -31,13 +40,18 @@ inline VoidPtr rtl_dma_alloc(SizeT size, SizeT align) {
return nullptr;
}
+ /// Check alignement according to architecture.
+ if ((align % kNeDMABestAlign) != 0) {
+ return nullptr;
+ }
+
UIntPtr addr = (UIntPtr) kDmaPoolPtr;
/// here we just align the address according to a `align` variable, i'd rather be a power of two
/// really.
addr = (addr + (align - 1)) & ~(align - 1);
- if ((addr + size) >= reinterpret_cast<UIntPtr>(kDmaPoolEnd)) {
+ if ((addr + size) > reinterpret_cast<UIntPtr>(kDmaPoolEnd)) {
err_global_get() = kErrorDmaExhausted;
return nullptr;
}
@@ -84,5 +98,4 @@ inline Void rtl_dma_flush(VoidPtr ptr, SizeT size_buffer) {
HAL::mm_memory_fence((VoidPtr) ((UInt8*) ptr + buf_idx));
}
}
-} // namespace Kernel
-#endif \ No newline at end of file
+} // namespace Kernel \ No newline at end of file
diff --git a/dev/kernel/FSKit/HeFS.h b/dev/kernel/FSKit/HeFS.h
index 08452a2b..845ef467 100644
--- a/dev/kernel/FSKit/HeFS.h
+++ b/dev/kernel/FSKit/HeFS.h
@@ -47,7 +47,7 @@ enum : UInt8 {
kHeFSScsiDrive = 0xC4, // SCSI Hard Drive
kHeFSFlashDrive = 0xC6,
kHeFSUnknown = 0xFF, // Unknown device.
- kHeFSDriveCount = 7,
+ kHeFSDriveCount = 8,
};
enum : UInt8 {
@@ -76,7 +76,7 @@ enum : UInt16 {
kHeFSFlagsSystem,
kHeFSFlagsArchive,
kHeFSFlagsDevice,
- kHeFSFlagsCount = 5
+ kHeFSFlagsCount = 7
};
inline constexpr UInt16 kHeFSFileKindRegular = 0x00;
diff --git a/dev/kernel/FirmwareKit/CoreBoot/BootNet.h b/dev/kernel/FirmwareKit/CoreBoot/BootNet.h
index b05f382e..3ed11363 100644
--- a/dev/kernel/FirmwareKit/CoreBoot/BootNet.h
+++ b/dev/kernel/FirmwareKit/CoreBoot/BootNet.h
@@ -8,9 +8,9 @@
#include <NeKit/Defines.h>
-#define kBootNetINetMagic "NETB"
+#define kBootNetINetMagic "ONET"
#define kBootNetINetMagicLength (4)
-
+#define kBootNetVersion (0x001)
#define kBootNetNameLen (256U)
/// @brief Netboot Internet Header
@@ -18,11 +18,11 @@
/// sent (if m_preflight = 0)
/// @note Can be used to patch ROMs too (if ImpliesProgram = 1)
typedef struct BOOTNET_INTERNET_HEADER {
- Kernel::Char NB1; /// magic char 1 'N'
- Kernel::Char NB2; /// magic char 2 'E'
- Kernel::Char NB3; /// magic char 3 'T'
- Kernel::Char NB4; /// magic char 4 'B'
-
+ Kernel::Char NB1; /// magic char 1 'O'
+ Kernel::Char NB2; /// magic char 2 'N'
+ Kernel::Char NB3; /// magic char 3 'E'
+ Kernel::Char NB4; /// magic char 4 'T'
+ Kernel::UInt16 Version;
Kernel::Char Name[kBootNetNameLen]; /// example: Modjo
Kernel::Int32 Length; /// the patch length.
Kernel::Char Target[kBootNetNameLen]; /// the target file.
diff --git a/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc b/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc
index 24a81af9..aeaeff52 100644
--- a/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc
+++ b/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc
@@ -216,7 +216,7 @@ Void mp_init_cores(VoidPtr vendor_ptr) noexcept {
kout << "Kind: LAPIC: OFF\r";
}
} else {
- kout << "Kind: UNKNOWN\r";
+ kout << "Kind: UNKNOWN: OFF\r";
}
entry_ptr += length;
diff --git a/dev/kernel/HALKit/AMD64/HalCoreInterruptHandler.cc b/dev/kernel/HALKit/AMD64/HalCoreInterruptHandler.cc
index 01456ae5..be6d0af5 100644
--- a/dev/kernel/HALKit/AMD64/HalCoreInterruptHandler.cc
+++ b/dev/kernel/HALKit/AMD64/HalCoreInterruptHandler.cc
@@ -6,6 +6,7 @@
#include <ArchKit/ArchKit.h>
#include <KernelKit/ProcessScheduler.h>
+#include <KernelKit/UserMgr.h>
#include <NeKit/KString.h>
#include <SignalKit/Signals.h>
@@ -126,33 +127,39 @@ EXTERN_C void idt_handle_ud(Kernel::UIntPtr rsp) {
process.Leak().Signal.Status = process.Leak().Status;
}
-/// @brief Enter syscall from assembly.
+/// @brief Enter syscall from assembly (libSystem only)
/// @param stack the stack pushed from assembly routine.
/// @return nothing.
-EXTERN_C Kernel::Void hal_system_call_enter(Kernel::UIntPtr rcx_syscall_index,
- Kernel::UIntPtr rdx_syscall_struct) {
+EXTERN_C Kernel::Void hal_system_call_enter(Kernel::UIntPtr rcx_hash,
+ Kernel::UIntPtr rdx_syscall_arg) {
hal_idt_send_eoi(50);
- if (rcx_syscall_index < kSysCalls.Count()) {
- if (kSysCalls[rcx_syscall_index].fHooked) {
- if (kSysCalls[rcx_syscall_index].fProc) {
- (kSysCalls[rcx_syscall_index].fProc)((Kernel::VoidPtr) rdx_syscall_struct);
+ if (!Kernel::kCurrentUser) return;
+
+ for (SizeT i = 0UL; i < kMaxDispatchCallCount; ++i) {
+ if (kSysCalls[i].fHooked && rcx_hash == kSysCalls[i].fHash) {
+ if (kSysCalls[i].fProc) {
+ (kSysCalls[i].fProc)((Kernel::VoidPtr) rdx_syscall_arg);
}
}
}
}
-/// @brief Enter Kernel call from assembly (DDK only).
+/// @brief Enter Kernel call from assembly (libDDK only).
/// @param stack the stack pushed from assembly routine.
/// @return nothing.
-EXTERN_C Kernel::Void hal_kernel_call_enter(Kernel::UIntPtr rcx_kerncall_index,
- Kernel::UIntPtr rdx_kerncall_struct) {
+EXTERN_C Kernel::Void hal_kernel_call_enter(Kernel::UIntPtr rcx_hash,
+ Kernel::UIntPtr rdx_kerncall_arg) {
hal_idt_send_eoi(51);
- if (rcx_kerncall_index < kKernCalls.Count()) {
- if (kKernCalls[rcx_kerncall_index].fHooked) {
- if (kKernCalls[rcx_kerncall_index].fProc) {
- (kKernCalls[rcx_kerncall_index].fProc)((Kernel::VoidPtr) rdx_kerncall_struct);
+ if (!Kernel::kRootUser) return;
+ if (Kernel::kCurrentUser != Kernel::kRootUser) return;
+ if (!Kernel::kCurrentUser->IsSuperUser()) return;
+
+ for (SizeT i = 0UL; i < kMaxDispatchCallCount; ++i) {
+ if (kKernCalls[i].fHooked && rcx_hash == kKernCalls[rcx_hash].fHash) {
+ if (kKernCalls[i].fProc) {
+ (kKernCalls[i].fProc)((Kernel::VoidPtr) rdx_kerncall_arg);
}
}
}
diff --git a/dev/kernel/HALKit/ARM64/APM/APM+IO.cc b/dev/kernel/HALKit/ARM64/APM/APM+IO.cc
index 3df8a407..e58fb782 100644
--- a/dev/kernel/HALKit/ARM64/APM/APM+IO.cc
+++ b/dev/kernel/HALKit/ARM64/APM/APM+IO.cc
@@ -9,11 +9,11 @@
using namespace Kernel;
-/// @brief Send APM command to it's space.
+/// @brief Send APM command to it's IO space.
/// @param base_dma the IO base port.
/// @param cmd the command.
/// @return status code.
-EXTERN_C Int32 apm_send_io_command(UInt16 cmd, APMPowerCmd value) {
+EXTERN_C Int32 apm_send_io_command(UInt16 cmd) {
switch (cmd) {
case kAPMPowerCommandReboot: {
asm volatile(
diff --git a/dev/kernel/HALKit/ARM64/HalACPIFactoryInterface.cc b/dev/kernel/HALKit/ARM64/HalACPIFactoryInterface.cc
index dc883239..fa678494 100644
--- a/dev/kernel/HALKit/ARM64/HalACPIFactoryInterface.cc
+++ b/dev/kernel/HALKit/ARM64/HalACPIFactoryInterface.cc
@@ -14,13 +14,13 @@ namespace Kernel {
ACPIFactoryInterface::ACPIFactoryInterface(VoidPtr rsp_ptr) : fRsdp(rsp_ptr), fEntries(0) {}
BOOL ACPIFactoryInterface::Shutdown() {
- apm_send_io_command(kAPMPowerCommandShutdown, 0);
+ apm_send_io_command(kAPMPowerCommandShutdown);
return NO;
}
/// @brief Reboot machine in either ACPI or by triple faulting.
/// @return nothing it's a reboot.
Void ACPIFactoryInterface::Reboot() {
- apm_send_io_command(kAPMPowerCommandReboot, 0);
+ apm_send_io_command(kAPMPowerCommandReboot);
}
} // namespace Kernel
diff --git a/dev/kernel/HALKit/ARM64/HalCoreInterruptHandler.cc b/dev/kernel/HALKit/ARM64/HalCoreInterruptHandler.cc
new file mode 100644
index 00000000..61a82314
--- /dev/null
+++ b/dev/kernel/HALKit/ARM64/HalCoreInterruptHandler.cc
@@ -0,0 +1,161 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/ProcessScheduler.h>
+#include <KernelKit/UserMgr.h>
+#include <NeKit/KString.h>
+#include <SignalKit/Signals.h>
+
+EXTERN_C Kernel::Void int_handle_breakpoint(Kernel::UIntPtr rip);
+ EXTERN_C BOOL mp_handle_gic_interrupt_el0(Void);
+
+EXTERN_C BOOL kEndOfInterrupt;
+EXTERN_C UInt8 kEndOfInterruptVector;
+
+STATIC BOOL kIsRunning = NO;
+
+/// @note This is managed by the system software.
+STATIC void hal_int_send_eoi(UInt8 vector) {
+ kEndOfInterrupt = YES;
+ kEndOfInterruptVector = vector;
+}
+
+/// @brief Handle GPF fault.
+/// @param rsp
+EXTERN_C Kernel::Void int_handle_gpf(Kernel::UIntPtr rsp) {
+ auto& process = Kernel::UserProcessScheduler::The().TheCurrentProcess();
+ process.Leak().Crash();
+
+ hal_int_send_eoi(13);
+
+ process.Leak().Signal.SignalArg = rsp;
+ process.Leak().Signal.SignalID = SIGKILL;
+ process.Leak().Signal.Status = process.Leak().Status;
+}
+
+/// @brief Handle page fault.
+/// @param rsp
+EXTERN_C void int_handle_pf(Kernel::UIntPtr rsp) {
+ auto& process = Kernel::UserProcessScheduler::The().TheCurrentProcess();
+ process.Leak().Crash();
+
+ hal_int_send_eoi(14);
+
+ process.Leak().Signal.SignalArg = rsp;
+ process.Leak().Signal.SignalID = SIGKILL;
+ process.Leak().Signal.Status = process.Leak().Status;
+}
+
+/// @brief Handle scheduler interrupt.
+EXTERN_C void int_handle_scheduler(Kernel::UIntPtr rsp) {
+ NE_UNUSED(rsp);
+
+ hal_int_send_eoi(32);
+
+ while (kIsRunning)
+ ;
+
+ kIsRunning = YES;
+
+ mp_handle_gic_interrupt_el0();
+
+ kIsRunning = NO;
+}
+
+/// @brief Handle math fault.
+/// @param rsp
+EXTERN_C void int_handle_math(Kernel::UIntPtr rsp) {
+ auto& process = Kernel::UserProcessScheduler::The().TheCurrentProcess();
+ process.Leak().Crash();
+
+ hal_int_send_eoi(8);
+
+ process.Leak().Signal.SignalArg = rsp;
+ process.Leak().Signal.SignalID = SIGKILL;
+ process.Leak().Signal.Status = process.Leak().Status;
+}
+
+/// @brief Handle any generic fault.
+/// @param rsp
+EXTERN_C void int_handle_generic(Kernel::UIntPtr rsp) {
+ auto& process = Kernel::UserProcessScheduler::The().TheCurrentProcess();
+ process.Leak().Crash();
+
+ hal_int_send_eoi(30);
+
+ Kernel::kout << "Kernel: Generic Process Fault.\r";
+
+ process.Leak().Signal.SignalArg = rsp;
+ process.Leak().Signal.SignalID = SIGKILL;
+ process.Leak().Signal.Status = process.Leak().Status;
+
+ Kernel::kout << "Kernel: SIGKILL status.\r";
+}
+
+EXTERN_C Kernel::Void int_handle_breakpoint(Kernel::UIntPtr rip) {
+ auto& process = Kernel::UserProcessScheduler::The().TheCurrentProcess();
+
+ hal_int_send_eoi(3);
+
+ process.Leak().Signal.SignalArg = rip;
+ process.Leak().Signal.SignalID = SIGTRAP;
+
+ process.Leak().Signal.Status = process.Leak().Status;
+
+ process.Leak().Status = Kernel::ProcessStatusKind::kFrozen;
+}
+
+/// @brief Handle #UD fault.
+/// @param rsp
+EXTERN_C void int_handle_ud(Kernel::UIntPtr rsp) {
+ auto& process = Kernel::UserProcessScheduler::The().TheCurrentProcess();
+ process.Leak().Crash();
+
+ hal_int_send_eoi(6);
+
+ process.Leak().Signal.SignalArg = rsp;
+ process.Leak().Signal.SignalID = SIGKILL;
+ process.Leak().Signal.Status = process.Leak().Status;
+}
+
+/// @brief Enter syscall from assembly (libSystem only)
+/// @param stack the stack pushed from assembly routine.
+/// @return nothing.
+EXTERN_C Kernel::Void hal_system_call_enter(Kernel::UIntPtr rcx_hash,
+ Kernel::UIntPtr rdx_syscall_arg) {
+ hal_int_send_eoi(50);
+
+ if (!Kernel::kCurrentUser) return;
+
+ for (SizeT i = 0UL; i < kMaxDispatchCallCount; ++i) {
+ if (kSysCalls[i].fHooked && rcx_hash == kSysCalls[i].fHash) {
+ if (kSysCalls[i].fProc) {
+ (kSysCalls[i].fProc)((Kernel::VoidPtr) rdx_syscall_arg);
+ }
+ }
+ }
+}
+
+/// @brief Enter Kernel call from assembly (libDDK only).
+/// @param stack the stack pushed from assembly routine.
+/// @return nothing.
+EXTERN_C Kernel::Void hal_kernel_call_enter(Kernel::UIntPtr rcx_hash,
+ Kernel::UIntPtr rdx_kerncall_arg) {
+ hal_int_send_eoi(51);
+
+ if (!Kernel::kRootUser) return;
+ if (Kernel::kCurrentUser != Kernel::kRootUser) return;
+ if (!Kernel::kCurrentUser->IsSuperUser()) return;
+
+ for (SizeT i = 0UL; i < kMaxDispatchCallCount; ++i) {
+ if (kKernCalls[i].fHooked && rcx_hash == kKernCalls[rcx_hash].fHash) {
+ if (kKernCalls[i].fProc) {
+ (kKernCalls[i].fProc)((Kernel::VoidPtr) rdx_kerncall_arg);
+ }
+ }
+ }
+}
diff --git a/dev/kernel/HALKit/ARM64/HalHandoverStub.s b/dev/kernel/HALKit/ARM64/HalHandoverStub.s
new file mode 100644
index 00000000..0f73cf7b
--- /dev/null
+++ b/dev/kernel/HALKit/ARM64/HalHandoverStub.s
@@ -0,0 +1,15 @@
+;; /*
+;; * ========================================================
+;; *
+;; * NeKernel
+;; * Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
+;; *
+;; * ========================================================
+;; */
+
+.section .ldr
+
+.quad 0xDAB4
+.word 100
+.word 0
+.word 122 \ No newline at end of file
diff --git a/dev/kernel/HALKit/ARM64/HalKernelPanic.cc b/dev/kernel/HALKit/ARM64/HalKernelPanic.cc
index d70fef00..91b2fe8a 100644
--- a/dev/kernel/HALKit/ARM64/HalKernelPanic.cc
+++ b/dev/kernel/HALKit/ARM64/HalKernelPanic.cc
@@ -45,8 +45,8 @@ Void RecoveryFactory::Recover() noexcept {
void ke_runtime_check(bool expr, const Char* file, const Char* line) {
if (!expr) {
- (Void)(kout << "FAILED: FILE: " << file << kendl);
- (Void)(kout << "FAILED: LINE: " << line << kendl);
+ (Void)(kout << "Kernel_Panic_FILE: " << file << kendl);
+ (Void)(kout << "Kernel_Panic_LINE: " << line << kendl);
ke_panic(RUNTIME_CHECK_FAILED, file); // Runtime Check failed
}
diff --git a/dev/kernel/KernelKit/PCI/IO.h b/dev/kernel/KernelKit/PCI/IO.h
index a7abc163..8ddba334 100644
--- a/dev/kernel/KernelKit/PCI/IO.h
+++ b/dev/kernel/KernelKit/PCI/IO.h
@@ -56,8 +56,8 @@ inline Array<UShort, Sz> make_ports(UShort base) {
}
} // namespace Kernel
-#ifdef __x86_64__
+#ifdef __NE_AMD64__
#include <KernelKit/PCI/IOArray+AMD64.inl>
#else
#error Please provide platform specific code for the I/O
-#endif // ifdef __x86_64__
+#endif // ifdef __NE_AMD64__
diff --git a/dev/kernel/KernelKit/PE.h b/dev/kernel/KernelKit/PE.h
index df5047a3..3aa8fbf2 100644
--- a/dev/kernel/KernelKit/PE.h
+++ b/dev/kernel/KernelKit/PE.h
@@ -44,8 +44,7 @@ typedef struct LDR_OPTIONAL_HEADER final {
Kernel::UInt32 SizeOfUninitializedData;
Kernel::UInt32 AddressOfEntryPoint;
Kernel::UInt32 BaseOfCode;
- Kernel::UInt32 BaseOfData;
- Kernel::UInt32 ImageBase;
+ Kernel::UInt64 ImageBase;
Kernel::UInt32 SectionAlignment;
Kernel::UInt32 FileAlignment;
Kernel::UInt16 MajorOperatingSystemVersion;
diff --git a/dev/kernel/KernelKit/ThreadLocalStorage.h b/dev/kernel/KernelKit/ThreadLocalStorage.h
index 6c764221..1b8e4821 100644
--- a/dev/kernel/KernelKit/ThreadLocalStorage.h
+++ b/dev/kernel/KernelKit/ThreadLocalStorage.h
@@ -27,8 +27,8 @@ struct THREAD_INFORMATION_BLOCK;
/// @brief Thread Information Block.
/// Located in GS on AMD64, other architectures have their own stuff. (64x0, 32x0, ARM64)
struct PACKED THREAD_INFORMATION_BLOCK final {
- Kernel::Char Cookie[kTLSCookieLen]{0}; //! Thread magic number.
- Kernel::VoidPtr Record{nullptr}; //! Thread information record.
+ Kernel::Char Cookie[kTLSCookieLen]{0}; //! Thread Magic Number.
+ Kernel::VoidPtr UserData{nullptr}; //! Thread Information Record (User defined canary structure)
};
///! @brief Cookie Sanity check.
diff --git a/dev/kernel/KernelKit/UserMgr.h b/dev/kernel/KernelKit/UserMgr.h
index ef1cc659..6fa8ba14 100644
--- a/dev/kernel/KernelKit/UserMgr.h
+++ b/dev/kernel/KernelKit/UserMgr.h
@@ -87,6 +87,9 @@ class User final {
Char mUserName[kMaxUserNameLen] = {0};
UInt64 mUserFNV{0UL};
};
+
+inline User* kCurrentUser = nullptr;
+inline User* kRootUser = nullptr;
} // namespace Kernel
#endif /* ifndef INC_USER_H */
diff --git a/dev/kernel/KernelKit/UserProcessScheduler.h b/dev/kernel/KernelKit/UserProcessScheduler.h
index 7c994726..5bc5b8d2 100644
--- a/dev/kernel/KernelKit/UserProcessScheduler.h
+++ b/dev/kernel/KernelKit/UserProcessScheduler.h
@@ -228,8 +228,6 @@ class UserProcessHelper final {
STATIC ErrorOr<PID> TheCurrentPID();
STATIC SizeT StartScheduling();
};
-
-const UInt32& sched_get_exit_code(void) noexcept;
} // namespace Kernel
#include <KernelKit/ThreadLocalStorage.h>
diff --git a/dev/kernel/NeKit/Utils.h b/dev/kernel/NeKit/Utils.h
index cdfcfe56..43526fc8 100644
--- a/dev/kernel/NeKit/Utils.h
+++ b/dev/kernel/NeKit/Utils.h
@@ -10,6 +10,8 @@
#include <NeKit/Defines.h>
namespace Kernel {
+/// ASCII API
+
Int rt_copy_memory(const voidPtr src, voidPtr dst, Size len);
Int rt_move_memory(const voidPtr src, voidPtr dst, Size len);
voidPtr rt_set_memory(voidPtr dst, UInt32 val, Size len);
@@ -27,6 +29,8 @@ Int rt_to_lower(Int c);
voidPtr rt_string_in_string(const Char* in, const Char* needle);
char* rt_string_has_char(Char* str, Char chr);
+/// UNICODE API
+
Int urt_string_cmp(const Char* src, const Char* cmp, Size len);
Void urt_set_memory(const voidPtr src, UInt32 dst, Size len);
Int urt_copy_memory(const voidPtr src, voidPtr dst, Size len);
diff --git a/dev/kernel/NetworkKit/IP.h b/dev/kernel/NetworkKit/IP.h
index 0b872352..0468d579 100644
--- a/dev/kernel/NetworkKit/IP.h
+++ b/dev/kernel/NetworkKit/IP.h
@@ -18,22 +18,22 @@ class IPFactory;
class RawIPAddress final {
private:
- explicit RawIPAddress(char bytes[4]);
+ explicit RawIPAddress(UInt8 bytes[4]);
~RawIPAddress() = default;
RawIPAddress& operator=(const RawIPAddress&) = delete;
RawIPAddress(const RawIPAddress&) = default;
public:
- Char* Address();
+ UInt8* Address();
- Char& operator[](const Size& index);
+ UInt8& operator[](const Size& index);
BOOL operator==(const RawIPAddress& ipv6);
BOOL operator!=(const RawIPAddress& ipv6);
private:
- Char fAddr[4];
+ UInt8 fAddr[4];
friend IPFactory; // it is the one creating these addresses, thus this
// is why the constructors are private.
@@ -44,22 +44,22 @@ class RawIPAddress final {
*/
class RawIPAddress6 final {
private:
- explicit RawIPAddress6(char Bytes[8]);
+ explicit RawIPAddress6(UInt8 Bytes[16]);
~RawIPAddress6() = default;
RawIPAddress6& operator=(const RawIPAddress6&) = delete;
RawIPAddress6(const RawIPAddress6&) = default;
public:
- char* Address() { return fAddr; }
+ UInt8* Address() { return fAddr; }
- char& operator[](const Size& index);
+ UInt8& operator[](const Size& index);
bool operator==(const RawIPAddress6& ipv6);
bool operator!=(const RawIPAddress6& ipv6);
private:
- char fAddr[8];
+ UInt8 fAddr[16];
friend IPFactory;
};
diff --git a/dev/kernel/SwapKit/DiskSwap.h b/dev/kernel/SwapKit/DiskSwap.h
index 1a0536c9..674524c8 100644
--- a/dev/kernel/SwapKit/DiskSwap.h
+++ b/dev/kernel/SwapKit/DiskSwap.h
@@ -35,21 +35,21 @@ class DiskSwapInterface final {
public:
/***********************************************************************************/
/// @brief Write memory chunk onto disk.
- /// @param fork_name The swap name to recognize this memory region.
- /// @param fork_name_len length of fork name.
+ /// @param name The swap name to recognize this memory region.
+ /// @param name_len length of fork name.
/// @param data the data packet.
/// @return Whether the swap was written to disk, or not.
/***********************************************************************************/
- BOOL Write(const Char* fork_name, SizeT fork_name_len, SWAP_DISK_HEADER* data);
+ BOOL Write(const Char* name, SizeT name_len, SWAP_DISK_HEADER* data);
/***********************************************************************************/
/// @brief Read memory chunk from disk.
- /// @param fork_name The swap name to recognize this memory region.
- /// @param fork_name_len length of fork name.
+ /// @param name The swap name to recognize this memory region.
+ /// @param name_len length of fork name.
/// @param data the data packet length.
/// @return Whether the swap was fetched to disk, or not.
/***********************************************************************************/
- _Output SWAP_DISK_HEADER* Read(const Char* fork_name, SizeT fork_name_len, SizeT data_len);
+ _Output SWAP_DISK_HEADER* Read(const Char* name, SizeT name_len, SizeT data_len);
};
/// @brief Swap disk header, containing information about the held virtual memory.
diff --git a/dev/kernel/kernel_rsrc.rsrc b/dev/kernel/kernel_rsrc.rsrc
index 5b1cb14f..a785a311 100644
--- a/dev/kernel/kernel_rsrc.rsrc
+++ b/dev/kernel/kernel_rsrc.rsrc
@@ -9,9 +9,9 @@ BEGIN
BLOCK "080904E4"
BEGIN
VALUE "CompanyName", "Amlal El Mahrouss"
- VALUE "FileDescription", "NeKernel"
+ VALUE "FileDescription", "NeKernel"
VALUE "FileVersion", KERNEL_VERSION
- VALUE "InternalName", "krnl"
+ VALUE "InternalName", "ne_kernel"
VALUE "LegalCopyright", "(c) 2024-2025 Amlal El Mahrouss, all rights reserved."
VALUE "OriginalFilename", "ne_kernel"
VALUE "ProductName", "NeKernel"
diff --git a/dev/kernel/src/Utils.cc b/dev/kernel/src/AsciiUtils.cc
index 087b6d5f..bfc56aec 100644
--- a/dev/kernel/src/Utils.cc
+++ b/dev/kernel/src/AsciiUtils.cc
@@ -8,40 +8,35 @@
namespace Kernel {
-STATIC Int rt_copy_memory_safe(const voidPtr src, voidPtr dst, Size len, Size dst_size);
+STATIC Int rt_copy_memory_safe(const voidPtr src, voidPtr dst, Size len, Size dst_size);
STATIC voidPtr rt_set_memory_safe(voidPtr dst, UInt32 value, Size len, Size dst_size);
Int32 rt_string_cmp(const Char* src, const Char* cmp, Size size) {
for (Size i = 0; i < size; ++i) {
- if (src[i] != cmp[i])
- return static_cast<Int32>(src[i]) - static_cast<Int32>(cmp[i]);
+ if (src[i] != cmp[i]) return static_cast<Int32>(src[i]) - static_cast<Int32>(cmp[i]);
}
return 0;
}
SizeT rt_string_len(const Char* str, SizeT max_len) {
SizeT len = 0;
- while (len < max_len && str[len] != '\0')
- ++len;
+ while (len < max_len && str[len] != '\0') ++len;
return len;
}
Size rt_string_len(const Char* ptr) {
Size cnt = 0;
- while (ptr[cnt] != '\0')
- ++cnt;
+ while (ptr[cnt] != '\0') ++cnt;
return cnt;
}
const Char* rt_alloc_string(const Char* src) {
- SizeT slen = rt_string_len(src);
+ SizeT slen = rt_string_len(src);
Char* buffer = new Char[slen + 1];
if (!buffer) return nullptr;
if (rt_copy_memory_safe(reinterpret_cast<voidPtr>(const_cast<Char*>(src)),
- reinterpret_cast<voidPtr>(buffer),
- slen,
- slen + 1) < 0) {
+ reinterpret_cast<voidPtr>(buffer), slen, slen + 1) < 0) {
delete[] buffer;
return nullptr;
}
@@ -59,17 +54,15 @@ STATIC Int rt_copy_memory_safe(const voidPtr src, voidPtr dst, Size len, Size ds
}
auto s = reinterpret_cast<const UInt8*>(src);
auto d = reinterpret_cast<UInt8*>(dst);
- for (Size i = 0; i < len; ++i)
- d[i] = s[i];
+ for (Size i = 0; i < len; ++i) d[i] = s[i];
return static_cast<Int>(len);
}
STATIC voidPtr rt_set_memory_safe(voidPtr dst, UInt32 value, Size len, Size dst_size) {
if (!dst || len > dst_size) return nullptr;
- auto p = reinterpret_cast<UInt8*>(dst);
+ auto p = reinterpret_cast<UInt8*>(dst);
UInt8 v = static_cast<UInt8>(value & 0xFF);
- for (Size i = 0; i < len; ++i)
- p[i] = v;
+ for (Size i = 0; i < len; ++i) p[i] = v;
return dst;
}
@@ -80,12 +73,12 @@ Void rt_zero_memory(voidPtr pointer, Size len) {
#ifdef __NE_ENFORCE_DEPRECATED_WARNINGS
[[deprecated("Use rt_set_memory_safe instead")]]
#endif
-voidPtr rt_set_memory(voidPtr src, UInt32 value, Size len) {
+voidPtr
+rt_set_memory(voidPtr src, UInt32 value, Size len) {
if (!src) return nullptr;
- auto p = reinterpret_cast<UInt8*>(src);
+ auto p = reinterpret_cast<UInt8*>(src);
UInt8 v = static_cast<UInt8>(value & 0xFF);
- for (Size i = 0; i < len; ++i)
- p[i] = v;
+ for (Size i = 0; i < len; ++i) p[i] = v;
return src;
}
@@ -97,13 +90,11 @@ Int rt_copy_memory(const voidPtr src, voidPtr dst, Size len) {
auto s = reinterpret_cast<const UInt8*>(src);
auto d = reinterpret_cast<UInt8*>(dst);
- for (Size i = 0; i < len; ++i)
- d[i] = s[i];
+ for (Size i = 0; i < len; ++i) d[i] = s[i];
return static_cast<Int>(len);
}
-
Int32 rt_to_uppercase(Int32 ch) {
return (ch >= 'a' && ch <= 'z') ? ch - 0x20 : ch;
}
@@ -113,9 +104,7 @@ Int32 rt_to_lower(Int32 ch) {
}
Int32 rt_is_alnum(Int32 ch) {
- return (ch >= 'a' && ch <= 'z') ||
- (ch >= 'A' && ch <= 'Z') ||
- (ch >= '0' && ch <= '9');
+ return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9');
}
Boolean rt_is_space(Char ch) {
@@ -141,18 +130,17 @@ Bool rt_to_string(Char* str, UInt64 value, Int32 base) {
str[i] = '\0';
// in-place
for (Int j = 0; j < i / 2; ++j) {
- Char tmp = str[j];
- str[j] = str[i - j - 1];
+ Char tmp = str[j];
+ str[j] = str[i - j - 1];
str[i - j - 1] = tmp;
}
#endif
return true;
}
-
VoidPtr rt_string_in_string(const Char* haystack, const Char* needle) {
SizeT needle_len = rt_string_len(needle);
- SizeT hay_len = rt_string_len(haystack);
+ SizeT hay_len = rt_string_len(haystack);
if (needle_len > hay_len) return nullptr;
for (SizeT i = 0; i <= hay_len - needle_len; ++i) {
@@ -173,11 +161,10 @@ Int32 rt_strcmp(const Char* a, const Char* b) {
while (a[i] != '\0' && b[i] != '\0' && a[i] == b[i]) {
++i;
}
- return static_cast<Int32>(static_cast<UInt8>(a[i]) -
- static_cast<UInt8>(b[i]));
+ return static_cast<Int32>(static_cast<UInt8>(a[i]) - static_cast<UInt8>(b[i]));
}
- // @uses the deprecated version callers should ensure 'len' is valid.
+// @uses the deprecated version callers should ensure 'len' is valid.
extern "C" void* memset(void* dst, int c, long long unsigned int len) {
return Kernel::rt_set_memory(dst, c, static_cast<Size>(len));
}
@@ -191,4 +178,4 @@ extern "C" Kernel::Int32 strcmp(const char* a, const char* b) {
return Kernel::rt_strcmp(a, b);
}
-}
+} // namespace Kernel
diff --git a/dev/kernel/src/CxxAbi-AMD64.cc b/dev/kernel/src/CxxAbi-AMD64.cc
index 5b0f7c3c..30c8306e 100644
--- a/dev/kernel/src/CxxAbi-AMD64.cc
+++ b/dev/kernel/src/CxxAbi-AMD64.cc
@@ -24,7 +24,14 @@ EXTERN_C Kernel::Void __cxa_pure_virtual(void* self) {
(Kernel::Void)(Kernel::kout << ", has unimplemented virtual functions.\r");
}
-EXTERN_C void ___chkstk_ms(void) {}
+EXTERN_C void ___chkstk_ms(PtrDiff frame_size) {
+ char* sp;
+ asm volatile("mov %%rsp, %0" : "=r"(sp));
+
+ for (PtrDiff offset = kPageSize; offset < frame_size; offset += kPageSize) {
+ sp[-offset] = 0;
+ }
+}
EXTERN_C int atexit(void (*f)()) {
if (__atexit_func_count >= kAtExitMacDestructors) return 1;
diff --git a/dev/kernel/src/CxxAbi-ARM64.cc b/dev/kernel/src/CxxAbi-ARM64.cc
index d351b024..e91eb958 100644
--- a/dev/kernel/src/CxxAbi-ARM64.cc
+++ b/dev/kernel/src/CxxAbi-ARM64.cc
@@ -37,7 +37,7 @@ EXTERN_C void __cxa_finalize(void* f) {
while (i--) {
if (__atexit_funcs[i].destructor_func) {
(*__atexit_funcs[i].destructor_func)();
- __atexit_funcs[i].destructor_func = 0;
+ __atexit_funcs[i].destructor_func = 0;
};
}
diff --git a/dev/kernel/src/FS/HeFS+FileSystemParser.cc b/dev/kernel/src/FS/HeFS+FileSystemParser.cc
index 893f43ef..39f8c0a1 100644
--- a/dev/kernel/src/FS/HeFS+FileSystemParser.cc
+++ b/dev/kernel/src/FS/HeFS+FileSystemParser.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.
------------------------------------------- */
@@ -758,8 +758,11 @@ _Output Bool HeFileSystemParser::Format(_Input _Output DriveTrait* mnt, _Input c
}
if (drv_std_get_size() < kHeFSMinimumDiskSize) {
- (Void)(kout << "HeFS recommends at least 128 GiB of free space." << kendl);
- (Void)(kout << "The OS will still try to format a HeFS disk here." << kendl);
+ (Void)(kout << "OpenHeFS recommends at least 128 GiB of free space." << kendl);
+ (Void)(
+ kout
+ << "The OS will still try to format a HeFS disk here anyway, don't expect perfect geometry."
+ << kendl);
}
HEFS_BOOT_NODE* boot = (HEFS_BOOT_NODE*) RTL_ALLOCA(sizeof(HEFS_BOOT_NODE));
@@ -1142,7 +1145,7 @@ STATIC DriveTrait kMountPoint;
/// @brief Initialize the HeFS filesystem.
/// @return To check its status, see err_local_get().
Boolean HeFS::fs_init_hefs(Void) noexcept {
- kout << "Creating HeFS disk...\r";
+ kout << "Verifying disk...\r";
kMountPoint = io_construct_main_drive();
diff --git a/dev/kernel/src/FS/NeFS+FileMgr.cc b/dev/kernel/src/FS/NeFS+FileMgr.cc
index 978a43a8..2fcfa2bb 100644
--- a/dev/kernel/src/FS/NeFS+FileMgr.cc
+++ b/dev/kernel/src/FS/NeFS+FileMgr.cc
@@ -14,18 +14,21 @@
/// BUGS: 0
namespace Kernel {
+static inline bool is_valid_nefs_catalog(NodePtr node);
+
/// @brief C++ constructor
NeFileSystemMgr::NeFileSystemMgr() {
- NeFileSystemParser* mParser = new NeFileSystemParser();
+ mParser = new NeFileSystemParser();
MUST_PASS(mParser);
- kout << "We are done allocating NeFileSystemParser...\r";
+ kout << "We are done allocating NeFileSystemParser...\n";
}
NeFileSystemMgr::~NeFileSystemMgr() {
if (mParser) {
- kout << "Destroying NeFileSystemParser...\r";
- mm_delete_class(&mParser);
+ kout << "Destroying NeFileSystemParser...\n";
+ delete mParser;
+ mParser = nullptr;
}
}
@@ -33,8 +36,10 @@ NeFileSystemMgr::~NeFileSystemMgr() {
/// @param path The filename
/// @return If it was deleted or not.
bool NeFileSystemMgr::Remove(_Input const Char* path) {
- if (path == nullptr || *path == 0) return false;
-
+ if (path == nullptr || *path == 0) {
+ kout << "NeFS: Remove called with null or empty path\n";
+ return false;
+ }
return mParser->RemoveCatalog(path);
}
@@ -42,27 +47,40 @@ bool NeFileSystemMgr::Remove(_Input const Char* path) {
/// @param path The filename path.
/// @return The Node pointer.
NodePtr NeFileSystemMgr::Create(_Input const Char* path) {
+ if (!path || *path == 0) {
+ kout << "NeFS: Create called with null or empty path\n";
+ return nullptr;
+ }
return rtl_node_cast(mParser->CreateCatalog(path));
}
-/// @brief Creates a node with is a directory.
+/// @brief Creates a node which is a directory.
/// @param path The filename path.
/// @return The Node pointer.
NodePtr NeFileSystemMgr::CreateDirectory(const Char* path) {
+ if (!path || *path == 0) {
+ kout << "NeFS: CreateDirectory called with null or empty path\n";
+ return nullptr;
+ }
return rtl_node_cast(mParser->CreateCatalog(path, 0, kNeFSCatalogKindDir));
}
-/// @brief Creates a node with is a alias.
+/// @brief Creates a node which is an alias.
/// @param path The filename path.
/// @return The Node pointer.
NodePtr NeFileSystemMgr::CreateAlias(const Char* path) {
+ if (!path || *path == 0) {
+ kout << "NeFS: CreateAlias called with null or empty path\n";
+ return nullptr;
+ }
return rtl_node_cast(mParser->CreateCatalog(path, 0, kNeFSCatalogKindAlias));
}
-/// @brief Creates a node with is a page file.
-/// @param path The filename path.
-/// @return The Node pointer.
NodePtr NeFileSystemMgr::CreateSwapFile(const Char* path) {
+ if (!path || *path == 0) {
+ kout << "NeFS: CreateSwapFile called with null or empty path\n";
+ return nullptr;
+ }
return rtl_node_cast(mParser->CreateCatalog(path, 0, kNeFSCatalogKindPage));
}
@@ -95,109 +113,163 @@ Char NeFileSystemHelper::MetaFile() {
/// @param r
/// @return
_Output NodePtr NeFileSystemMgr::Open(_Input const Char* path, _Input const Char* r) {
- if (!path || *path == 0) return nullptr;
-
- if (!r || *r == 0) return nullptr;
-
+ if (!path || *path == 0) {
+ kout << "NeFS: Open called with null or empty path\n";
+ return nullptr;
+ }
+ if (!r || *r == 0) {
+ kout << "NeFS: Open called with null or empty mode string\n";
+ return nullptr;
+ }
auto catalog = mParser->GetCatalog(path);
-
+ if (!catalog) {
+ kout << "NeFS: Open could not find catalog for path\n";
+ return nullptr;
+ }
return rtl_node_cast(catalog);
}
-/// @brief Writes to a catalog's fork.
-/// @param node the node ptr.
-/// @param data the data.
-/// @param flags the size.
-/// @return
Void NeFileSystemMgr::Write(_Input NodePtr node, _Input VoidPtr data, _Input Int32 flags,
_Input SizeT size) {
- if (!node) return;
- if (!size) return;
-
+ if (!is_valid_nefs_catalog(node)) {
+ kout << "NeFS: Write called with invalid node pointer\n";
+ return;
+ }
+ if (!data) {
+ kout << "NeFS: Write called with null data pointer\n";
+ return;
+ }
+ if (!size || size > kNeFSForkSize) {
+ (Void)(kout << "NeFS: Write called with invalid size: " << hex_number(size));
+ kout << "\n";
+ return;
+ }
constexpr auto kDataForkName = kNeFSDataFork;
this->Write(kDataForkName, node, data, flags, size);
}
-/// @brief Read from filesystem fork.
-/// @param node the catalog node.
-/// @param flags the flags with it.
-/// @param sz the size to read.
-/// @return
_Output VoidPtr NeFileSystemMgr::Read(_Input NodePtr node, _Input Int32 flags, _Input SizeT size) {
- if (!node) return nullptr;
- if (!size) return nullptr;
-
+ if (!is_valid_nefs_catalog(node)) {
+ kout << "NeFS: Read called with invalid node pointer\n";
+ return nullptr;
+ }
+ if (!size || size > kNeFSForkSize) {
+ (Void)(kout << "NeFS: Write called with invalid size: " << hex_number(size));
+ kout << "\n";
+ return nullptr;
+ }
constexpr auto kDataForkName = kNeFSDataFork;
return this->Read(kDataForkName, node, flags, size);
}
Void NeFileSystemMgr::Write(_Input const Char* name, _Input NodePtr node, _Input VoidPtr data,
_Input Int32 flags, _Input SizeT size) {
- if (!size || size > kNeFSForkSize) return;
-
- if (!data) return;
-
+ if (!is_valid_nefs_catalog(node)) {
+ kout << "NeFS: Write(fork) called with invalid node pointer\n";
+ return;
+ }
+ if (!name || *name == 0) {
+ kout << "NeFS: Write(fork) called with null or empty fork name\n";
+ return;
+ }
+ if (!data) {
+ kout << "NeFS: Write(fork) called with null data pointer\n";
+ return;
+ }
+ if (!size || size > kNeFSForkSize) {
+ (Void)(kout << "NeFS: Write called with invalid size: " << hex_number(size));
+ kout << "\n";
+ return;
+ }
NE_UNUSED(flags);
-
- if ((reinterpret_cast<NEFS_CATALOG_STRUCT*>(node))->Kind == kNeFSCatalogKindFile)
- mParser->WriteCatalog(reinterpret_cast<NEFS_CATALOG_STRUCT*>(node)->Name,
- (flags & kFileFlagRsrc ? true : false), data, size, name);
+ auto cat = reinterpret_cast<NEFS_CATALOG_STRUCT*>(node);
+ if (cat->Kind == kNeFSCatalogKindFile) {
+ mParser->WriteCatalog(cat->Name, (flags & kFileFlagRsrc ? true : false), data, size, name);
+ }
}
_Output VoidPtr NeFileSystemMgr::Read(_Input const Char* name, _Input NodePtr node,
_Input Int32 flags, _Input SizeT sz) {
- if (sz > kNeFSForkSize) return nullptr;
-
- if (!sz) return nullptr;
-
+ if (!is_valid_nefs_catalog(node)) {
+ kout << "NeFS: Read(fork) called with invalid node pointer\n";
+ return nullptr;
+ }
+ if (!name || *name == 0) {
+ kout << "NeFS: Read(fork) called with null or empty fork name\n";
+ return nullptr;
+ }
+ if (!sz || sz > kNeFSForkSize) {
+ (Void)(kout << "NeFS: Write called with invalid size: " << hex_number(sz));
+ kout << "\n";
+ return nullptr;
+ }
NE_UNUSED(flags);
-
- if ((reinterpret_cast<NEFS_CATALOG_STRUCT*>(node))->Kind == kNeFSCatalogKindFile)
- return mParser->ReadCatalog(reinterpret_cast<NEFS_CATALOG_STRUCT*>(node),
- (flags & kFileFlagRsrc ? true : false), sz, name);
-
+ auto cat = reinterpret_cast<NEFS_CATALOG_STRUCT*>(node);
+ if (cat->Kind == kNeFSCatalogKindFile) {
+ return mParser->ReadCatalog(cat, (flags & kFileFlagRsrc ? true : false), sz, name);
+ }
return nullptr;
}
-/// @brief Seek from Catalog.
-/// @param node
-/// @param off
-/// @retval true always returns false, this is unimplemented.
-/// @retval false always returns this, it is unimplemented.
-
_Output Bool NeFileSystemMgr::Seek(NodePtr node, SizeT off) {
- if (!node || off == 0) return false;
-
+ if (!is_valid_nefs_catalog(node)) {
+ kout << "NeFS: Seek called with invalid node pointer\n";
+ return false;
+ }
+ // Allow off == 0
return mParser->Seek(reinterpret_cast<NEFS_CATALOG_STRUCT*>(node), off);
}
-/// @brief Tell where the catalog is.
+/// @brief Tell current offset within catalog.
/// @param node
-/// @retval true always returns false, this is unimplemented.
-/// @retval false always returns this, it is unimplemented.
-
+/// @return kFileMgrNPos if invalid, else current offset.
_Output SizeT NeFileSystemMgr::Tell(NodePtr node) {
- if (!node) return kFileMgrNPos;
-
+ if (!is_valid_nefs_catalog(node)) {
+ kout << "NeFS: Tell called with invalid node pointer\n";
+ return kFileMgrNPos;
+ }
return mParser->Tell(reinterpret_cast<NEFS_CATALOG_STRUCT*>(node));
}
-/// @brief Rewinds the catalog.
+/// @brief Rewinds the catalog
/// @param node
-/// @retval true always returns false, this is unimplemented.
-/// @retval false always returns this, it is unimplemented.
-
+/// @return False if invalid, nah? calls Seek(node, 0).
_Output Bool NeFileSystemMgr::Rewind(NodePtr node) {
- if (!node) return false;
-
+ if (!is_valid_nefs_catalog(node)) {
+ kout << "NeFS: Rewind called with invalid node pointer\n";
+ return false;
+ }
return this->Seek(node, 0);
}
-/// @brief Returns the filesystem parser.
-/// @return the Filesystem parser class.
+/// @brief Returns the parser of NeFS.
_Output NeFileSystemParser* NeFileSystemMgr::GetParser() noexcept {
return mParser;
}
+
+static inline bool is_valid_nefs_catalog(NodePtr node) {
+ if (!node) return false;
+ auto cat = reinterpret_cast<NEFS_CATALOG_STRUCT*>(node);
+ switch (cat->Kind) {
+ case kNeFSCatalogKindFile:
+ case kNeFSCatalogKindDir:
+ case kNeFSCatalogKindAlias:
+ case kNeFSCatalogKindPage:
+ break;
+ default:
+ return false;
+ }
+ bool null_found = false;
+ for (int i = 0; i < kNeFSCatalogNameLen; ++i) {
+ if (cat->Name[i] == 0) {
+ null_found = true;
+ break;
+ }
+ }
+ if (!null_found) return false;
+ return true;
+}
+
} // namespace Kernel
#endif // ifdef __FSKIT_INCLUDES_NEFS__
diff --git a/dev/kernel/src/FS/NeFS+FileSystemParser.cc b/dev/kernel/src/FS/NeFS+FileSystemParser.cc
index dd0a1d9a..18595e9f 100644
--- a/dev/kernel/src/FS/NeFS+FileSystemParser.cc
+++ b/dev/kernel/src/FS/NeFS+FileSystemParser.cc
@@ -46,15 +46,35 @@ Kernel::SizeT drv_std_get_size();
/***********************************************************************************/
/// This file implements the New extended File System.
-/// New extended File System implements a flat linked-list based algortihm.
-/// /
-/// /Path1/ /Path2/
-/// /readme.rtf /ListContents.pef /readme.lnk <-- symlink.
-/// /Path1/readme.rtf
+/// New extended File System implements a flat linked-list based algorithm.
+/// /
+/// /Path1/ /Path2/
+/// /readme.rtf /ListContents.pef /readme.lnk <-- symlink.
+/// /Path1/readme.rtf
/***********************************************************************************/
+static inline bool is_valid_size(SizeT size, SizeT max_size) {
+ return size > 0 && size <= max_size;
+}
-STATIC MountpointInterface kMountpoint;
+static inline bool is_valid_lba(Lba lba, DriveTrait& drive) {
+ NEFS_ROOT_PARTITION_BLOCK part_block;
+ drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress;
+ drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK);
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&part_block);
+ drive.fInput(drive.fPacket);
+
+ if (!drive.fPacket.fPacketGood) {
+ return false;
+ }
+
+ // Compute the maximum LBA (DiskSize / sector size)
+ SizeT sectorSize = drive.fSectorSz;
+ Lba maxLba = part_block.DiskSize / sectorSize;
+ return (lba >= part_block.StartCatalog) && (lba < maxLba);
+}
+
+STATIC MountpointInterface kMountpoint;
/***********************************************************************************/
/// @brief Creates a new fork inside the New filesystem partition.
/// @param catalog it's catalog
@@ -62,86 +82,69 @@ STATIC MountpointInterface kMountpoint;
/// @return the fork
/***********************************************************************************/
_Output BOOL NeFileSystemParser::CreateFork(_Input NEFS_FORK_STRUCT& the_fork) {
- if (the_fork.ForkName[0] != 0 && the_fork.CatalogName[0] != 0 && the_fork.DataSize > 0) {
- auto catalog = this->GetCatalog(the_fork.CatalogName);
-
- if (!catalog) return NO;
-
- Lba lba = catalog->DataFork;
-
- (Void)(kout << "Fork LBA: " << hex_number(lba) << kendl);
-
- if (lba < kNeFSCatalogStartAddress) return NO;
-
- auto& drv = kMountpoint.A();
-
- Lba lba_prev = lba;
-
- NEFS_FORK_STRUCT prev_fork;
- NEFS_FORK_STRUCT cur_fork;
-
- /// do not check for anything. Loop until we get what we want, that is a free fork zone.
- while (drv.fPacket.fPacketGood) {
- drv.fPacket.fPacketLba = lba;
- drv.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT);
- drv.fPacket.fPacketContent = &cur_fork;
-
- drv.fInput(drv.fPacket);
-
- (Void)(kout << "Next fork: " << hex_number(cur_fork.NextSibling) << kendl);
-
- if (cur_fork.Flags & kNeFSFlagCreated) {
- kout << "Error: Fork does exists, not overwriting this one.\r";
-
- /// sanity check.
- if (KStringBuilder::Equals(cur_fork.ForkName, the_fork.ForkName) &&
- KStringBuilder::Equals(cur_fork.CatalogName, the_fork.CatalogName))
- break;
+ if (the_fork.ForkName[0] == 0 || the_fork.CatalogName[0] == 0 || the_fork.DataSize == 0) {
+ return NO;
+ }
- lba_prev = lba;
- lba = cur_fork.NextSibling;
+ auto catalog = this->GetCatalog(the_fork.CatalogName);
+ if (!catalog) return NO;
- prev_fork = cur_fork;
- } else {
- /// This is a check that we have, in order to link the previous fork
- /// entry.
- if (lba >= kNeFSCatalogStartAddress) {
- drv.fPacket.fPacketLba = lba_prev;
- drv.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT);
- drv.fPacket.fPacketContent = &prev_fork;
+ Lba lba = catalog->DataFork;
+ if (lba < kNeFSCatalogStartAddress) {
+ delete catalog;
+ return NO;
+ }
- prev_fork.NextSibling = lba;
+ auto& drv = kMountpoint.A();
+ Lba lba_prev = lba;
+ NEFS_FORK_STRUCT prev_fork{};
+ NEFS_FORK_STRUCT cur_fork{};
- /// write to disk.
- drv.fOutput(drv.fPacket);
- }
+ while (true) {
+ drv.fPacket.fPacketLba = lba;
+ drv.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT);
+ drv.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&cur_fork);
+ drv.fInput(drv.fPacket);
+ if (!drv.fPacket.fPacketGood) {
+ delete catalog;
+ return NO;
+ }
+ if (cur_fork.Flags & kNeFSFlagCreated) {
+ if (KStringBuilder::Equals(cur_fork.ForkName, the_fork.ForkName) &&
+ KStringBuilder::Equals(cur_fork.CatalogName, the_fork.CatalogName)) {
break;
}
+ lba_prev = lba;
+ lba = cur_fork.NextSibling;
+ prev_fork = cur_fork;
+ } else {
+ if (lba >= kNeFSCatalogStartAddress) {
+ prev_fork.NextSibling = lba;
+ drv.fPacket.fPacketLba = lba_prev;
+ drv.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT);
+ drv.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&prev_fork);
+ drv.fOutput(drv.fPacket);
+ }
+ break;
}
+ }
- the_fork.Flags |= kNeFSFlagCreated;
- the_fork.DataOffset = lba - sizeof(NEFS_FORK_STRUCT);
- the_fork.PreviousSibling = lba_prev;
- the_fork.NextSibling = the_fork.DataOffset - the_fork.DataSize;
-
- drv.fPacket.fPacketLba = lba;
- drv.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT);
- drv.fPacket.fPacketContent = &the_fork;
-
- drv.fOutput(drv.fPacket);
-
- fs_ifs_write(&kMountpoint, drv, MountpointInterface::kDriveIndexA);
-
- /// log what we have now.
- (Void)(kout << "Fork offset is at: " << hex_number(the_fork.DataOffset) << kendl);
+ SizeT sectorCount = (the_fork.DataSize + kNeFSSectorSz - 1) / kNeFSSectorSz;
+ the_fork.DataOffset = lba + 1;
+ the_fork.PreviousSibling = lba_prev;
+ the_fork.NextSibling = lba + 1 + sectorCount;
+ the_fork.Flags |= kNeFSFlagCreated;
- (Void)(kout << "Wrote fork metadata at: " << hex_number(lba) << kendl);
+ drv.fPacket.fPacketLba = lba;
+ drv.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT);
+ drv.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&the_fork);
+ drv.fOutput(drv.fPacket);
- return YES;
- }
+ fs_ifs_write(&kMountpoint, drv, MountpointInterface::kDriveIndexA);
- return NO;
+ delete catalog;
+ return YES;
}
/***********************************************************************************/
@@ -153,17 +156,19 @@ _Output BOOL NeFileSystemParser::CreateFork(_Input NEFS_FORK_STRUCT& the_fork) {
_Output NEFS_FORK_STRUCT* NeFileSystemParser::FindFork(_Input NEFS_CATALOG_STRUCT* catalog,
_Input const Char* name,
_Input Boolean is_data) {
- auto& drive = kMountpoint.A();
- NEFS_FORK_STRUCT* the_fork = nullptr;
+ if (!catalog || !name) return nullptr;
- Lba lba = is_data ? catalog->DataFork : catalog->ResourceFork;
+ auto& drive = kMountpoint.A();
+ Lba lba = is_data ? catalog->DataFork : catalog->ResourceFork;
+ NEFS_FORK_STRUCT local_buf{};
- while (lba != 0) {
+ while (lba >= kNeFSCatalogStartAddress) {
drive.fPacket.fPacketLba = lba;
drive.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT);
- drive.fPacket.fPacketContent = (VoidPtr) the_fork;
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&local_buf);
- rt_copy_memory((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime, 16);
+ rt_copy_memory((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime,
+ rt_string_len("fs/nefs-packet"));
if (auto res = fs_ifs_read(&kMountpoint, drive, this->mDriveIndex); res) {
switch (res) {
@@ -176,21 +181,23 @@ _Output NEFS_FORK_STRUCT* NeFileSystemParser::FindFork(_Input NEFS_CATALOG_STRUC
case 3:
err_global_get() = kErrorNoSuchDisk;
break;
-
default:
break;
}
return nullptr;
}
- if (KStringBuilder::Equals(the_fork->ForkName, name)) {
- break;
+ if (KStringBuilder::Equals(local_buf.ForkName, name) &&
+ KStringBuilder::Equals(local_buf.CatalogName, catalog->Name)) {
+ auto result = new NEFS_FORK_STRUCT();
+ rt_copy_memory(&local_buf, result, sizeof(NEFS_FORK_STRUCT));
+ return result;
}
- lba = the_fork->NextSibling;
+ lba = local_buf.NextSibling;
}
- return the_fork;
+ return nullptr;
}
/***********************************************************************************/
@@ -215,18 +222,20 @@ _Output NEFS_CATALOG_STRUCT* NeFileSystemParser::CreateCatalog(_Input const Char
_Input const Int32& kind) {
kout << "CreateCatalog(*...*)\r";
+ if (!name) return nullptr;
+ SizeT nameLen = rt_string_len(name);
+ if (nameLen == 0) return nullptr;
+
Lba out_lba = 0UL;
kout << "Checking for path separator...\r";
/// a directory should have a slash in the end.
- if (kind == kNeFSCatalogKindDir &&
- name[rt_string_len(name) - 1] != NeFileSystemHelper::Separator())
+ if (kind == kNeFSCatalogKindDir && name[nameLen - 1] != NeFileSystemHelper::Separator())
return nullptr;
/// a file shouldn't have a slash in the end.
- if (kind != kNeFSCatalogKindDir &&
- name[rt_string_len(name) - 1] == NeFileSystemHelper::Separator())
+ if (kind != kNeFSCatalogKindDir && name[nameLen - 1] == NeFileSystemHelper::Separator())
return nullptr;
NEFS_CATALOG_STRUCT* catalog_copy = this->FindCatalog(name, out_lba);
@@ -234,245 +243,217 @@ _Output NEFS_CATALOG_STRUCT* NeFileSystemParser::CreateCatalog(_Input const Char
if (catalog_copy) {
kout << "Catalog already exists: " << name << ".\r";
err_global_get() = kErrorFileExists;
-
delete catalog_copy;
catalog_copy = nullptr;
-
return nullptr;
}
- Char* parent_name = (Char*) mm_alloc_ptr(sizeof(Char) * rt_string_len(name), Yes, No);
+ Char* parent_name = (Char*) mm_alloc_ptr(nameLen + 1, Yes, No);
+ rt_copy_memory(const_cast<Char*>(name), parent_name, nameLen + 1);
- /// Locate parent catalog, to then allocate right after it.
-
- for (SizeT index_fill = 0; index_fill < rt_string_len(name); ++index_fill) {
- parent_name[index_fill] = name[index_fill];
- }
-
- if (*parent_name == 0) {
- kout << "Parent name is NUL.\r";
+ if (nameLen < 2) {
+ mm_free_ptr(parent_name);
err_global_get() = kErrorFileNotFound;
return nullptr;
}
- SizeT index_reverse_copy = rt_string_len(parent_name);
-
- // zero character it.
- parent_name[--index_reverse_copy] = 0;
-
- // mandatory / character, zero it.
- parent_name[--index_reverse_copy] = 0;
-
- while (parent_name[index_reverse_copy] != NeFileSystemHelper::Separator()) {
+ SizeT index_reverse_copy = nameLen - 1;
+ if (parent_name[index_reverse_copy] == NeFileSystemHelper::Separator()) {
+ parent_name[index_reverse_copy] = 0;
+ --index_reverse_copy;
+ }
+ while (index_reverse_copy > 0 &&
+ parent_name[index_reverse_copy] != NeFileSystemHelper::Separator()) {
parent_name[index_reverse_copy] = 0;
--index_reverse_copy;
}
+ if (index_reverse_copy == 0 && parent_name[0] != NeFileSystemHelper::Separator()) {
+ mm_free_ptr(parent_name);
+ err_global_get() = kErrorFileNotFound;
+ return nullptr;
+ }
NEFS_CATALOG_STRUCT* catalog = this->FindCatalog(parent_name, out_lba);
-
mm_free_ptr(parent_name);
auto& drive = kMountpoint.A();
-
if (catalog && catalog->Kind == kNeFSCatalogKindFile) {
kout << "Parent is a file.\r";
delete catalog;
-
return nullptr;
} else if (!catalog) {
Char part_block[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0};
-
- drive.fPacket.fPacketContent = part_block;
- drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK);
- drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress;
-
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(part_block);
+ drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK);
+ drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress;
drive.fInput(drive.fPacket);
NEFS_ROOT_PARTITION_BLOCK* blk_nefs = (NEFS_ROOT_PARTITION_BLOCK*) part_block;
out_lba = blk_nefs->StartCatalog;
}
- if (drive.fPacket.fPacketReadOnly) return nullptr;
+ if (drive.fPacket.fPacketReadOnly) {
+ delete catalog;
+ return nullptr;
+ }
NEFS_CATALOG_STRUCT* child_catalog = new NEFS_CATALOG_STRUCT();
-
- child_catalog->Checksum = 0;
- child_catalog->ResourceForkSize = 0UL;
- child_catalog->DataForkSize = 0UL;
- child_catalog->CatalogFlags = kNeFSStatusUnlocked;
- child_catalog->NextSibling = out_lba;
- child_catalog->PrevSibling = out_lba;
- child_catalog->Kind = kind;
+ child_catalog->Checksum = 0;
+ child_catalog->ResourceForkSize = 0UL;
+ child_catalog->DataForkSize = 0UL;
+ child_catalog->CatalogFlags = kNeFSStatusUnlocked;
+ child_catalog->NextSibling = out_lba;
+ child_catalog->PrevSibling = out_lba;
+ child_catalog->Kind = kind;
child_catalog->Flags |= kNeFSFlagCreated;
child_catalog->CatalogFlags = flags;
- SizeT i = rt_string_len(name);
-
- // get rid pf \0
+ SizeT i = nameLen;
--i;
-
if (kind == kNeFSCatalogKindDir) --i;
-
while (name[i] != '/') --i;
-
- rt_copy_memory((VoidPtr) (name + i), (VoidPtr) child_catalog->Name, rt_string_len(name));
+ rt_copy_memory((VoidPtr) (name + i), (VoidPtr) child_catalog->Name, rt_string_len(name) - i);
NEFS_CATALOG_STRUCT temporary_catalog{};
-
- Lba start_free = out_lba;
+ Lba start_free = out_lba;
rt_copy_memory((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime,
rt_string_len("fs/nefs-packet"));
Char buf_part_block[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0};
-
- drive.fPacket.fPacketContent = buf_part_block;
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(buf_part_block);
drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK);
drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress;
-
drive.fInput(drive.fPacket);
NEFS_ROOT_PARTITION_BLOCK* part_block = (NEFS_ROOT_PARTITION_BLOCK*) buf_part_block;
-
- drive.fPacket.fPacketContent = &temporary_catalog;
- drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT);
- drive.fPacket.fPacketLba = start_free;
-
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&temporary_catalog);
+ drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT);
+ drive.fPacket.fPacketLba = start_free;
drive.fInput(drive.fPacket);
if (part_block->FreeCatalog < 1) {
delete child_catalog;
- child_catalog = nullptr;
-
+ delete catalog;
return nullptr;
}
kout << "Start finding catalog to allocate or empty space...\r";
- while (start_free >= part_block->StartCatalog) {
- // ========================== //
- // Allocate catalog now...
- // ========================== //
+ SizeT catalogSectors = (sizeof(NEFS_CATALOG_STRUCT) + drive.fSectorSz - 1) / drive.fSectorSz;
+ while (start_free < part_block->StartCatalog + (part_block->CatalogCount * catalogSectors)) {
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&temporary_catalog);
+ drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT);
+ drive.fPacket.fPacketLba = start_free;
+ drive.fInput(drive.fPacket);
+
if ((temporary_catalog.Flags & kNeFSFlagCreated) == 0) {
- child_catalog->NextSibling = start_free + sizeof(NEFS_CATALOG_STRUCT);
+ child_catalog->NextSibling = start_free + catalogSectors;
- drive.fPacket.fPacketContent = &temporary_catalog;
+ NEFS_CATALOG_STRUCT placeholder{};
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&placeholder);
drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT);
drive.fPacket.fPacketLba = start_free;
-
drive.fOutput(drive.fPacket);
child_catalog->DataFork = part_block->DiskSize - start_free;
child_catalog->ResourceFork = child_catalog->DataFork;
- drive.fPacket.fPacketContent = child_catalog;
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(child_catalog);
drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT);
drive.fPacket.fPacketLba = start_free;
-
drive.fOutput(drive.fPacket);
- // Get NeFS partition's block.
-
- drive.fPacket.fPacketContent = buf_part_block;
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(buf_part_block);
drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK);
drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress;
-
drive.fInput(drive.fPacket);
- part_block->FreeSectors -= 1;
+ part_block->FreeSectors -= catalogSectors;
part_block->CatalogCount += 1;
part_block->FreeCatalog -= 1;
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(part_block);
+ drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK);
+ drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress;
drive.fOutput(drive.fPacket);
delete catalog;
- catalog = nullptr;
-
NEFS_CATALOG_STRUCT* found_catalog = new NEFS_CATALOG_STRUCT();
rt_copy_memory(&temporary_catalog, found_catalog, sizeof(NEFS_CATALOG_STRUCT));
+ delete child_catalog;
return found_catalog;
} else if ((temporary_catalog.Flags & kNeFSFlagCreated) &&
KStringBuilder::Equals(temporary_catalog.Name, name)) {
rt_copy_memory(&temporary_catalog, child_catalog, sizeof(NEFS_CATALOG_STRUCT));
-
+ delete catalog;
return child_catalog;
}
- start_free = start_free + sizeof(NEFS_CATALOG_STRUCT);
-
- drive.fPacket.fPacketContent = &temporary_catalog;
- drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT);
- drive.fPacket.fPacketLba = start_free;
-
- drive.fInput(drive.fPacket);
+ start_free += catalogSectors;
}
+ delete child_catalog;
delete catalog;
return nullptr;
}
+/***********************************************************************************/
/// @brief Make a EPM+NeFS drive out of the disk.
/// @param drive The drive to write on.
/// @return If it was sucessful, see err_global_get().
+/***********************************************************************************/
bool NeFileSystemParser::Format(_Input _Output DriveTrait* drive, _Input const Int32 flags,
const Char* part_name) {
- if (*part_name == 0) return false;
-
+ if (!part_name || *part_name == 0) return false;
NE_UNUSED(flags);
// verify disk.
drive->fVerify(drive->fPacket);
-
rt_copy_memory((VoidPtr) "fs/nefs-packet", drive->fPacket.fPacketMime,
rt_string_len("fs/nefs-packet"));
-
- // if disk isn't good, then error out.
- if (false == drive->fPacket.fPacketGood) {
+ if (!drive->fPacket.fPacketGood) {
err_global_get() = kErrorDiskIsCorrupted;
return false;
}
Char fs_buf[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0};
+ Lba start = drive->fLbaStart;
- Lba start = drive->fLbaStart;
-
- drive->fPacket.fPacketContent = fs_buf;
+ drive->fPacket.fPacketContent = reinterpret_cast<VoidPtr>(fs_buf);
drive->fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK);
drive->fPacket.fPacketLba = start;
-
drive->fInput(drive->fPacket);
NEFS_ROOT_PARTITION_BLOCK* part_block = (NEFS_ROOT_PARTITION_BLOCK*) fs_buf;
-
if (rt_string_cmp(kNeFSIdent, part_block->Ident, kNeFSIdentLen) == 0) return true;
const auto kNeFSUntitledHD = part_name;
-
rt_copy_memory((VoidPtr) kNeFSIdent, (VoidPtr) part_block->Ident, kNeFSIdentLen);
-
rt_copy_memory((VoidPtr) kNeFSUntitledHD, (VoidPtr) part_block->PartitionName,
rt_string_len(kNeFSUntitledHD));
- SizeT sectorCount = drv_std_get_sector_count();
- SizeT diskSize = drv_std_get_size();
-
- part_block->Version = kNeFSVersionInteger;
+ SizeT sectorCount = drv_std_get_sector_count();
+ SizeT sectorSize = drive->fSectorSz;
+ SizeT totalBytes = sectorCount * sectorSize;
+ SizeT catalogEntries = totalBytes / sizeof(NEFS_CATALOG_STRUCT);
+ SizeT catalogSectors = (sizeof(NEFS_CATALOG_STRUCT) + sectorSize - 1) / sectorSize;
+ part_block->Version = kNeFSVersionInteger;
part_block->Kind = kNeFSPartitionTypeStandard;
- part_block->StartCatalog = start + sizeof(NEFS_CATALOG_STRUCT);
+ part_block->StartCatalog = start + catalogSectors;
part_block->Flags = 0UL;
- part_block->CatalogCount = sectorCount / sizeof(NEFS_CATALOG_STRUCT);
- part_block->FreeSectors = sectorCount / sizeof(NEFS_CATALOG_STRUCT) - 1;
+ part_block->CatalogCount = catalogEntries;
+ part_block->FreeCatalog = catalogEntries - 1;
part_block->SectorCount = sectorCount;
- part_block->DiskSize = diskSize;
- part_block->SectorSize = drive->fSectorSz;
- part_block->FreeCatalog = sectorCount / sizeof(NEFS_CATALOG_STRUCT) - 1;
+ part_block->DiskSize = totalBytes;
+ part_block->SectorSize = sectorSize;
+ part_block->FreeSectors = sectorCount - catalogSectors;
- drive->fPacket.fPacketContent = fs_buf;
+ drive->fPacket.fPacketContent = reinterpret_cast<VoidPtr>(fs_buf);
drive->fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK);
drive->fPacket.fPacketLba = start;
-
drive->fOutput(drive->fPacket);
(Void)(kout << "Drive kind: " << drive->fProtocol() << kendl);
@@ -486,110 +467,108 @@ bool NeFileSystemParser::Format(_Input _Output DriveTrait* drive, _Input const I
return true;
}
+/***********************************************************************************/
/// @brief Writes the data fork into a specific catalog.
/// @param catalog the catalog itself
/// @param data the data.
-/// @return if the catalog w rote the contents successfully.
+/// @return if the catalog wrote the contents successfully.
+/***********************************************************************************/
bool NeFileSystemParser::WriteCatalog(_Input const Char* catalog_name, Bool is_rsrc_fork,
_Input VoidPtr data, _Input SizeT size_of_data,
_Input const Char* fork_name) {
- if (size_of_data < 1) return No;
+ if (size_of_data < 1) return NO;
- auto buf = new UInt8[size_of_data];
- rt_set_memory(buf, 0, size_of_data);
+ auto catalog = this->GetCatalog(catalog_name);
+ if (!catalog) {
+ kout << "NeFS: WriteCatalog failed to find catalog: " << catalog_name << "\n";
+ return false;
+ }
- rt_copy_memory(data, buf, size_of_data);
+ SizeT maxSize = is_rsrc_fork ? catalog->ResourceForkSize : catalog->DataForkSize;
- auto& drive = kMountpoint.A();
+ if (!is_valid_size(size_of_data, maxSize)) {
+ (Void)(kout << "NeFS: WriteCatalog called with invalid size: " << hex_number(size_of_data));
+ kout << "\n";
- rt_copy_memory((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime,
- rt_string_len("fs/nefs-packet"));
+ delete catalog;
+ return false;
+ }
- auto catalog = this->GetCatalog(catalog_name);
+ Lba startFork = is_rsrc_fork ? catalog->ResourceFork : catalog->DataFork;
+ auto& drive = kMountpoint.A();
- if (!catalog) {
- delete[] buf;
- buf = nullptr;
- return NO;
+ if (!is_valid_lba(startFork, drive)) {
+ (Void)(kout << "NeFS: WriteCatalog called with invalid LBA: " << hex_number(startFork));
+ kout << "\n";
+
+ delete catalog;
+ return false;
}
- auto startFork = (!is_rsrc_fork) ? catalog->DataFork : catalog->ResourceFork;
+ NEFS_ROOT_PARTITION_BLOCK part_block;
+ drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress;
+ drive.fPacket.fPacketSize = sizeof(part_block);
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&part_block);
+ drive.fInput(drive.fPacket);
- delete catalog;
- catalog = nullptr;
+ auto buf = new UInt8[size_of_data];
+ rt_set_memory(buf, 0, size_of_data);
+ rt_copy_memory(data, buf, size_of_data);
+ rt_copy_memory((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime,
+ rt_string_len("fs/nefs-packet"));
NEFS_FORK_STRUCT* fork_data_input = new NEFS_FORK_STRUCT();
NEFS_FORK_STRUCT prev_fork{};
- (Void)(kout << hex_number(startFork) << kendl);
-
- // sanity check of the fork position as the condition to run the loop.
- while (startFork >= kNeFSCatalogStartAddress) {
- drive.fPacket.fPacketContent = fork_data_input;
+ while (startFork >= part_block.StartCatalog && drive.fPacket.fPacketGood) {
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(fork_data_input);
drive.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT);
drive.fPacket.fPacketLba = startFork;
-
drive.fInput(drive.fPacket);
- (Void)(kout << hex_number(fork_data_input->DataSize) << kendl);
- (Void)(kout << hex_number(size_of_data) << kendl);
- (Void)(kout << hex_number(fork_data_input->Flags) << kendl);
- (Void)(kout << fork_name << kendl);
- (Void)(kout << fork_data_input->ForkName << kendl);
- (Void)(kout << fork_data_input->CatalogName << kendl);
- (Void)(kout << catalog_name << kendl);
+ if (!drive.fPacket.fPacketGood) {
+ break;
+ }
if ((fork_data_input->Flags & kNeFSFlagCreated) &&
KStringBuilder::Equals(fork_data_input->ForkName, fork_name) &&
KStringBuilder::Equals(fork_data_input->CatalogName, catalog_name) &&
fork_data_input->DataSize == size_of_data) {
- // ===================================================== //
- // Store the blob now, into chunks.
- // ===================================================== //
-
- auto cnt = size_of_data / kNeFSSectorSz;
- auto cnter = 0UL;
- auto compute_sz = kNeFSSectorSz;
-
- if (cnt < 1) break;
-
- while (compute_sz) {
- drive.fPacket.fPacketContent = buf + (cnter * kNeFSSectorSz);
- drive.fPacket.fPacketSize = compute_sz;
- drive.fPacket.fPacketLba = fork_data_input->DataOffset;
-
- (Void)(kout << "data offset: " << hex_number(cnt * kNeFSSectorSz) << kendl);
-
+ SizeT bytes_left = size_of_data;
+ SizeT offset = 0;
+ Lba base_lba = fork_data_input->DataOffset;
+
+ while (bytes_left > 0) {
+ SizeT chunk = (bytes_left > kNeFSSectorSz) ? kNeFSSectorSz : bytes_left;
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(buf + offset);
+ drive.fPacket.fPacketSize = chunk;
+ drive.fPacket.fPacketLba = base_lba + (offset / kNeFSSectorSz);
drive.fOutput(drive.fPacket);
-
- compute_sz /= (size_of_data / cnt);
- ++cnter;
+ offset += chunk;
+ bytes_left -= chunk;
}
- (Void)(kout << "wrote data at offset: " << hex_number(fork_data_input->DataOffset) << kendl);
-
delete fork_data_input;
delete[] buf;
-
+ delete catalog;
return true;
}
- // stumble upon a fork, store it.
-
prev_fork = *fork_data_input;
-
startFork = fork_data_input->NextSibling;
}
- delete[] buf;
delete fork_data_input;
-
+ delete[] buf;
+ delete catalog;
return false;
}
+/***********************************************************************************/
/// @brief
/// @param catalog_name the catalog name.
/// @return the newly found catalog.
+/***********************************************************************************/
_Output NEFS_CATALOG_STRUCT* NeFileSystemParser::FindCatalog(_Input const Char* catalog_name,
Lba& out_lba, Bool search_hidden,
Bool local_search) {
@@ -600,144 +579,102 @@ _Output NEFS_CATALOG_STRUCT* NeFileSystemParser::FindCatalog(_Input const Char*
rt_copy_memory((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime,
rt_string_len("fs/nefs-packet"));
-
- drive.fPacket.fPacketContent = &part;
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&part);
drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK);
drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress;
-
drive.fInput(drive.fPacket);
auto start_catalog_lba = kNeFSCatalogStartAddress;
- if (!KStringBuilder::Equals(catalog_name, NeFileSystemHelper::Root()) && local_search) {
- Char parent_name[kNeFSCatalogNameLen] = {0};
+ // Helper lambda to scan from a given LBA
+ auto scan_from = [&](Lba lba_start, Bool allow_hidden) -> NEFS_CATALOG_STRUCT* {
+ Lba cursor = lba_start;
+ NEFS_CATALOG_STRUCT tmp{};
+ while (cursor >= part.StartCatalog && drive.fPacket.fPacketGood) {
+ drive.fPacket.fPacketLba = cursor;
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&tmp);
+ drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT);
+ drive.fInput(drive.fPacket);
- for (SizeT indexFill = 0; indexFill < rt_string_len(catalog_name); ++indexFill) {
- parent_name[indexFill] = catalog_name[indexFill];
+ if (KStringBuilder::Equals(
+ tmp.Name, catalog_name + (rt_string_len(catalog_name) - rt_string_len(tmp.Name)))) {
+ if (tmp.Status == kNeFSStatusLocked && !allow_hidden) {
+ err_global_get() = kErrorFileLocked;
+ return nullptr;
+ }
+ if (!(tmp.Flags & kNeFSFlagCreated)) {
+ err_global_get() = kErrorFileNotFound;
+ return nullptr;
+ }
+ NEFS_CATALOG_STRUCT* catalog_ptr = new NEFS_CATALOG_STRUCT();
+ rt_copy_memory(&tmp, catalog_ptr, sizeof(NEFS_CATALOG_STRUCT));
+ out_lba = cursor;
+ return catalog_ptr;
+ }
+ cursor = tmp.NextSibling;
}
+ return nullptr;
+ };
- SizeT indexReverseCopy = rt_string_len(parent_name);
-
- // zero character.
- parent_name[--indexReverseCopy] = 0;
-
- // mandatory '/' character.
- parent_name[--indexReverseCopy] = 0;
+ if (!KStringBuilder::Equals(catalog_name, NeFileSystemHelper::Root()) && local_search) {
+ Char parent_name[kNeFSCatalogNameLen] = {0};
+ SizeT nameLen = rt_string_len(catalog_name);
+ rt_copy_memory(const_cast<Char*>(catalog_name), parent_name, nameLen + 1);
- while (parent_name[indexReverseCopy] != NeFileSystemHelper::Separator()) {
+ SizeT indexReverseCopy = nameLen - 1;
+ if (parent_name[indexReverseCopy] == NeFileSystemHelper::Separator()) {
parent_name[indexReverseCopy] = 0;
--indexReverseCopy;
}
-
- NEFS_CATALOG_STRUCT* parent_catalog = this->FindCatalog(parent_name, out_lba);
-
- if (parent_catalog && !KStringBuilder::Equals(parent_name, NeFileSystemHelper::Root())) {
- start_catalog_lba = parent_catalog->NextSibling;
-
- delete parent_catalog;
- parent_catalog = nullptr;
-
- local_search = YES;
- } else if (parent_catalog) {
- start_catalog_lba = parent_catalog->NextSibling;
-
- local_search = YES;
-
- delete parent_catalog;
- parent_catalog = nullptr;
- } else if (!parent_catalog) {
+ while (indexReverseCopy > 0 &&
+ parent_name[indexReverseCopy] != NeFileSystemHelper::Separator()) {
+ parent_name[indexReverseCopy] = 0;
+ --indexReverseCopy;
+ }
+ if (indexReverseCopy == 0 && parent_name[0] != NeFileSystemHelper::Separator()) {
return nullptr;
}
- }
- NEFS_CATALOG_STRUCT temporary_catalog{};
-
- SizeT i = rt_string_len(catalog_name);
-
- // get rid of \0
- --i;
-
- if (catalog_name[i] == '/') --i;
-
- while (catalog_name[i] != '/') --i;
-
- const Char* tmp_name = (catalog_name + i);
-
-kNeFSSearchThroughCatalogList:
- while (drive.fPacket.fPacketGood) {
- drive.fPacket.fPacketLba = start_catalog_lba;
- drive.fPacket.fPacketContent = &temporary_catalog;
- drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT);
-
- drive.fInput(drive.fPacket);
-
- if (KStringBuilder::Equals(tmp_name, temporary_catalog.Name)) {
- if (temporary_catalog.Status == kNeFSStatusLocked && !search_hidden) {
- err_global_get() = kErrorFileLocked;
-
- goto NeFSContinueSearch;
- }
-
- /// ignore unallocated catalog, break
- if (!(temporary_catalog.Flags & kNeFSFlagCreated)) {
- err_global_get() = kErrorFileNotFound;
-
- goto NeFSContinueSearch;
- }
-
- (Void)(kout << "Found available catalog at: " << hex_number(start_catalog_lba) << kendl);
- (Void)(kout << "Found available catalog at: " << temporary_catalog.Name << kendl);
-
- NEFS_CATALOG_STRUCT* catalog_ptr = new NEFS_CATALOG_STRUCT();
- rt_copy_memory(&temporary_catalog, catalog_ptr, sizeof(NEFS_CATALOG_STRUCT));
-
- out_lba = start_catalog_lba;
- return catalog_ptr;
+ NEFS_CATALOG_STRUCT* parent_catalog =
+ this->FindCatalog(parent_name, out_lba, search_hidden, NO);
+ if (parent_catalog) {
+ start_catalog_lba = parent_catalog->NextSibling;
+ delete parent_catalog;
+ NEFS_CATALOG_STRUCT* found = scan_from(start_catalog_lba, search_hidden);
+ if (found) return found;
}
-
- NeFSContinueSearch:
- start_catalog_lba = temporary_catalog.NextSibling;
-
- if (start_catalog_lba < part.StartCatalog) break;
- }
-
- if (local_search) {
- local_search = false;
- start_catalog_lba = part.StartCatalog;
-
- goto kNeFSSearchThroughCatalogList;
}
- err_global_get() = kErrorFileNotFound;
-
- out_lba = 0UL;
-
- return nullptr;
+ return scan_from(part.StartCatalog, search_hidden);
}
+/***********************************************************************************/
/// @brief Get catalog from filesystem.
/// @param name the catalog's name/
/// @return
+/***********************************************************************************/
_Output NEFS_CATALOG_STRUCT* NeFileSystemParser::GetCatalog(_Input const Char* name) {
Lba unused = 0;
- return this->FindCatalog(name, unused, YES);
+ return this->FindCatalog(name, unused, YES, YES);
}
+/***********************************************************************************/
/// @brief Closes a catalog, (frees it).
/// @param catalog the catalog to close.
/// @return
+/***********************************************************************************/
_Output Boolean NeFileSystemParser::CloseCatalog(_Input _Output NEFS_CATALOG_STRUCT* catalog) {
if (!catalog) return false;
-
delete catalog;
catalog = nullptr;
-
return true;
}
+/***********************************************************************************/
/// @brief Mark catalog as removed.
/// @param catalog The catalog structure.
/// @return if the catalog was removed or not.
+/***********************************************************************************/
_Output Boolean NeFileSystemParser::RemoveCatalog(_Input const Char* catalog_name) {
if (!catalog_name || KStringBuilder::Equals(catalog_name, NeFileSystemHelper::Root())) {
err_global_get() = kErrorInternal;
@@ -745,46 +682,80 @@ _Output Boolean NeFileSystemParser::RemoveCatalog(_Input const Char* catalog_nam
}
Lba out_lba = 0;
- auto catalog = this->FindCatalog(catalog_name, out_lba);
+ auto catalog = this->FindCatalog(catalog_name, out_lba, YES, YES);
+ if (!catalog) return false;
+
+ auto& drive = kMountpoint.A();
+ NEFS_FORK_STRUCT fork_buf{};
+ Lba fork_lba = catalog->DataFork;
+ while (fork_lba >= kNeFSCatalogStartAddress) {
+ drive.fPacket.fPacketLba = fork_lba;
+ drive.fPacket.fPacketSize = sizeof(fork_buf);
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&fork_buf);
+ drive.fInput(drive.fPacket);
+
+ fork_buf.Flags &= (~kNeFSFlagCreated);
+ fork_buf.Flags |= kNeFSFlagDeleted;
+
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&fork_buf);
+ drive.fPacket.fPacketSize = sizeof(fork_buf);
+ drive.fPacket.fPacketLba = fork_lba;
+ drive.fOutput(drive.fPacket);
+
+ fork_lba = fork_buf.NextSibling;
+ }
+
+ fork_lba = catalog->ResourceFork;
+ while (fork_lba >= kNeFSCatalogStartAddress) {
+ drive.fPacket.fPacketLba = fork_lba;
+ drive.fPacket.fPacketSize = sizeof(fork_buf);
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&fork_buf);
+ drive.fInput(drive.fPacket);
+
+ fork_buf.Flags &= (~kNeFSFlagCreated);
+ fork_buf.Flags |= kNeFSFlagDeleted;
+
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&fork_buf);
+ drive.fPacket.fPacketSize = sizeof(fork_buf);
+ drive.fPacket.fPacketLba = fork_lba;
+ drive.fOutput(drive.fPacket);
+
+ fork_lba = fork_buf.NextSibling;
+ }
- if (out_lba >= kNeFSCatalogStartAddress || catalog->Flags & kNeFSFlagCreated) {
+ if (out_lba >= kNeFSCatalogStartAddress || (catalog->Flags & kNeFSFlagCreated)) {
catalog->Flags &= (~kNeFSFlagCreated);
catalog->Flags |= kNeFSFlagDeleted;
- auto& drive = kMountpoint.A();
-
rt_copy_memory((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime,
rt_string_len("fs/nefs-packet"));
-
- drive.fPacket.fPacketLba = out_lba; // the catalog position.
- drive.fPacket.fPacketSize =
- sizeof(NEFS_CATALOG_STRUCT); // size of catalog. roughly the sector size.
- drive.fPacket.fPacketContent = catalog; // the catalog itself.
-
- drive.fOutput(drive.fPacket); // send packet.
+ drive.fPacket.fPacketLba = out_lba;
+ drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT);
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(catalog);
+ drive.fOutput(drive.fPacket);
Char partitionBlockBuf[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0};
-
- drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress;
- drive.fPacket.fPacketContent = partitionBlockBuf;
+ drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress;
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(partitionBlockBuf);
drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK);
-
drive.fInput(drive.fPacket);
- NEFS_ROOT_PARTITION_BLOCK* part_block =
- reinterpret_cast<NEFS_ROOT_PARTITION_BLOCK*>(partitionBlockBuf);
-
- --part_block->CatalogCount;
+ NEFS_ROOT_PARTITION_BLOCK* part_block = (NEFS_ROOT_PARTITION_BLOCK*) partitionBlockBuf;
+ if (part_block->CatalogCount > 0) --part_block->CatalogCount;
++part_block->FreeSectors;
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(part_block);
+ drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK);
+ drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress;
drive.fOutput(drive.fPacket);
+ delete catalog;
+ catalog = nullptr;
return true;
}
delete catalog;
catalog = nullptr;
-
return false;
}
@@ -798,7 +769,6 @@ _Output Boolean NeFileSystemParser::RemoveCatalog(_Input const Char* catalog_nam
/// @param dataSz
/// @return
/***********************************************************************************/
-
VoidPtr NeFileSystemParser::ReadCatalog(_Input _Output NEFS_CATALOG_STRUCT* catalog,
_Input Bool is_rsrc_fork, _Input SizeT dataSz,
_Input const Char* forkName) {
@@ -806,35 +776,43 @@ VoidPtr NeFileSystemParser::ReadCatalog(_Input _Output NEFS_CATALOG_STRUCT* cata
err_global_get() = kErrorInvalidData;
return nullptr;
}
+ // Validate size against fork size
+ SizeT maxSize = is_rsrc_fork ? catalog->ResourceForkSize : catalog->DataForkSize;
+ if (!is_valid_size(dataSz, maxSize)) {
+ kout << "NeFS: ReadCatalog called with invalid size: ";
+ hex_number(dataSz);
+ kout << "\n";
+ return nullptr;
+ }
- NE_UNUSED(dataSz);
-
- Lba dataForkLba = (!is_rsrc_fork) ? catalog->DataFork : catalog->ResourceFork;
-
- NEFS_FORK_STRUCT* fs_buf = new NEFS_FORK_STRUCT();
- auto& drive = kMountpoint.A();
+ Lba dataForkLba = is_rsrc_fork ? catalog->ResourceFork : catalog->DataFork;
+ auto& drive = kMountpoint.A();
+ if (!is_valid_lba(dataForkLba, drive)) {
+ kout << "NeFS: ReadCatalog called with invalid LBA: ";
+ hex_number(dataForkLba);
+ kout << "\n";
+ return nullptr;
+ }
+ auto* fs_buf = new NEFS_FORK_STRUCT();
rt_copy_memory((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime,
rt_string_len("fs/nefs-packet"));
NEFS_FORK_STRUCT* fs_fork_data = nullptr;
-
- while (dataForkLba > kNeFSCatalogStartAddress) {
+ while (dataForkLba >= kNeFSCatalogStartAddress) {
drive.fPacket.fPacketLba = dataForkLba;
drive.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT);
- drive.fPacket.fPacketContent = fs_buf;
-
+ drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(fs_buf);
drive.fInput(drive.fPacket);
fs_fork_data = fs_buf;
-
(Void)(kout << "ForkName: " << fs_fork_data->ForkName << kendl);
(Void)(kout << "CatalogName: " << fs_fork_data->CatalogName << kendl);
if (KStringBuilder::Equals(forkName, fs_fork_data->ForkName) &&
- KStringBuilder::Equals(catalog->Name, fs_fork_data->CatalogName))
+ KStringBuilder::Equals(catalog->Name, fs_fork_data->CatalogName)) {
break;
-
+ }
dataForkLba = fs_fork_data->NextSibling;
}
@@ -842,7 +820,6 @@ VoidPtr NeFileSystemParser::ReadCatalog(_Input _Output NEFS_CATALOG_STRUCT* cata
delete fs_buf;
return nullptr;
}
-
return fs_fork_data;
}
@@ -852,11 +829,9 @@ VoidPtr NeFileSystemParser::ReadCatalog(_Input _Output NEFS_CATALOG_STRUCT* cata
/// @param off where to seek.
/// @return if the seeking was successful.
/***********************************************************************************/
-
bool NeFileSystemParser::Seek(_Input _Output NEFS_CATALOG_STRUCT* catalog, SizeT off) {
NE_UNUSED(catalog);
NE_UNUSED(off);
-
err_global_get() = kErrorUnimplemented;
return false;
}
@@ -866,10 +841,8 @@ bool NeFileSystemParser::Seek(_Input _Output NEFS_CATALOG_STRUCT* catalog, SizeT
/// @param catalog
/// @return The position on the file.
/***********************************************************************************/
-
SizeT NeFileSystemParser::Tell(_Input _Output NEFS_CATALOG_STRUCT* catalog) {
NE_UNUSED(catalog);
-
err_global_get() = kErrorUnimplemented;
return 0;
}
@@ -880,14 +853,10 @@ namespace Kernel::NeFS {
/***********************************************************************************/
Boolean fs_init_nefs(Void) noexcept {
kout << "Creating HeFS disk...\r";
-
kMountpoint.A() = io_construct_main_drive();
-
if (kMountpoint.A().fPacket.fPacketReadOnly == YES)
ke_panic(RUNTIME_CHECK_FILESYSTEM, "Main disk cannot be mounted.");
-
NeFileSystemParser parser;
-
return parser.Format(&kMountpoint.A(), 0, kNeFSVolumeName);
}
} // namespace Kernel::NeFS
diff --git a/dev/kernel/src/Network/IPAddr.cc b/dev/kernel/src/Network/IPAddr.cc
index beb69470..b341af8f 100644
--- a/dev/kernel/src/Network/IPAddr.cc
+++ b/dev/kernel/src/Network/IPAddr.cc
@@ -8,11 +8,11 @@
#include <NetworkKit/IP.h>
namespace Kernel {
-Char* RawIPAddress::Address() {
+UInt8* RawIPAddress::Address() {
return fAddr;
}
-RawIPAddress::RawIPAddress(char bytes[4]) {
+RawIPAddress::RawIPAddress(UInt8 bytes[4]) {
rt_copy_memory(bytes, fAddr, 4);
}
@@ -32,30 +32,30 @@ BOOL RawIPAddress::operator!=(const RawIPAddress& ipv4) {
return true;
}
-Char& RawIPAddress::operator[](const Size& index) {
+UInt8& RawIPAddress::operator[](const Size& index) {
kout << "[RawIPAddress::operator[]] Fetching Index...\r";
- static char IP_PLACEHOLDER = '0';
- if (index > 4) return IP_PLACEHOLDER;
+ static UInt8 IP_PLACEHOLDER = '0';
+ if (index >= 4) return IP_PLACEHOLDER;
return fAddr[index];
}
-RawIPAddress6::RawIPAddress6(char bytes[8]) {
- rt_copy_memory(bytes, fAddr, 8);
+RawIPAddress6::RawIPAddress6(UInt8 bytes[16]) {
+ rt_copy_memory(bytes, fAddr, 16);
}
-char& RawIPAddress6::operator[](const Size& index) {
+UInt8& RawIPAddress6::operator[](const Size& index) {
kout << "[RawIPAddress6::operator[]] Fetching Index...\r";
- static char IP_PLACEHOLDER = '0';
- if (index > 8) return IP_PLACEHOLDER;
+ static UInt8 IP_PLACEHOLDER = '0';
+ if (index >= 16) return IP_PLACEHOLDER;
return fAddr[index];
}
bool RawIPAddress6::operator==(const RawIPAddress6& ipv6) {
- for (SizeT index = 0; index < 8; ++index) {
+ for (SizeT index = 0; index < 16; ++index) {
if (ipv6.fAddr[index] != fAddr[index]) return false;
}
@@ -63,23 +63,28 @@ bool RawIPAddress6::operator==(const RawIPAddress6& ipv6) {
}
bool RawIPAddress6::operator!=(const RawIPAddress6& ipv6) {
- for (SizeT index = 0; index < 8; ++index) {
+ for (SizeT index = 0; index < 16; ++index) {
if (ipv6.fAddr[index] == fAddr[index]) return false;
}
return true;
}
+/// @todo
ErrorOr<KString> IPFactory::ToKString(Ref<RawIPAddress6>& ipv6) {
- auto str = KStringBuilder::Construct(ipv6.Leak().Address());
+ NE_UNUSED(ipv6);
+ auto str = KStringBuilder::Construct(0);
return str;
}
+/// @todo
ErrorOr<KString> IPFactory::ToKString(Ref<RawIPAddress>& ipv4) {
- auto str = KStringBuilder::Construct(ipv4.Leak().Address());
+ NE_UNUSED(ipv4);
+ auto str = KStringBuilder::Construct(0);
return str;
}
+/// @note Doesn't catch IPs such as 256.999.0.1, UNSAFE!
bool IPFactory::IpCheckVersion4(const Char* ip) {
if (!ip) return NO;
@@ -89,6 +94,7 @@ bool IPFactory::IpCheckVersion4(const Char* ip) {
if (ip[base] == '.') {
cnter = 0;
} else {
+ if (!rt_is_alnum(ip[base])) return false;
if (cnter == 3) return false;
++cnter;
diff --git a/dev/kernel/src/ThreadLocalStorage.cc b/dev/kernel/src/ThreadLocalStorage.cc
index ec315ddf..03a71f1a 100644
--- a/dev/kernel/src/ThreadLocalStorage.cc
+++ b/dev/kernel/src/ThreadLocalStorage.cc
@@ -15,7 +15,7 @@
/***********************************************************************************/
/// @bugs: 0
/// @file ThreadLocalStorage.cc
-/// @brief Process Thread Local Storage.
+/// @brief NeKernel Thread Local Storage.
/***********************************************************************************/
using namespace Kernel;
@@ -27,15 +27,11 @@ using namespace Kernel;
*/
Boolean tls_check_tib(THREAD_INFORMATION_BLOCK* tib_ptr) {
- if (!tib_ptr || !tib_ptr->Record) return false;
+ if (!tib_ptr) return false;
- ICodec encoder;
- const Char* tib_as_bytes = encoder.AsBytes<THREAD_INFORMATION_BLOCK*>(tib_ptr);
-
- kout << "TLS: Validating the TIB...\r";
-
- return tib_as_bytes[kCookieMag0Idx] == kCookieMag0 &&
- tib_as_bytes[kCookieMag1Idx] == kCookieMag1 && tib_as_bytes[kCookieMag2Idx] == kCookieMag2;
+ return tib_ptr->Cookie[kCookieMag0Idx] == kCookieMag0 &&
+ tib_ptr->Cookie[kCookieMag1Idx] == kCookieMag1 &&
+ tib_ptr->Cookie[kCookieMag2Idx] == kCookieMag2;
}
/**
@@ -51,11 +47,5 @@ EXTERN_C Bool tls_check_syscall_impl(Kernel::VoidPtr tib_ptr) noexcept {
THREAD_INFORMATION_BLOCK* tib = reinterpret_cast<THREAD_INFORMATION_BLOCK*>(tib_ptr);
- if (!tls_check_tib(tib)) {
- kout << "TLS: Failed because of an invalid TIB...\r";
- return No;
- }
-
- kout << "TLS Pass.\r";
- return Yes;
+ return tls_check_tib(tib);
}
diff --git a/dev/kernel/src/UserProcessScheduler.cc b/dev/kernel/src/UserProcessScheduler.cc
index e417cc8d..eff53745 100644
--- a/dev/kernel/src/UserProcessScheduler.cc
+++ b/dev/kernel/src/UserProcessScheduler.cc
@@ -25,12 +25,6 @@
///! BUGS: 0
namespace Kernel {
-/***********************************************************************************/
-/// @brief Exit Code global variable.
-/***********************************************************************************/
-
-STATIC UInt32 kLastExitCode = 0U;
-
USER_PROCESS::USER_PROCESS() = default;
USER_PROCESS::~USER_PROCESS() = default;
@@ -38,10 +32,6 @@ USER_PROCESS::~USER_PROCESS() = default;
/// @note Not thread-safe.
/// @return Int32 the last exit code.
-const UInt32& sched_get_exit_code(void) noexcept {
- return kLastExitCode;
-}
-
/***********************************************************************************/
/// @brief Crashes the current process.
/***********************************************************************************/
@@ -135,6 +125,11 @@ ErrorOr<VoidPtr> USER_PROCESS::New(SizeT sz, SizeT pad_amount) {
if (!this->HeapTree) {
this->HeapTree = new PROCESS_HEAP_TREE<VoidPtr>();
+ if (!this->HeapTree) {
+ this->Crash();
+ return ErrorOr<VoidPtr>(-kErrorHeapOutOfMemory);
+ }
+
this->HeapTree->EntryPad = pad_amount;
this->HeapTree->EntrySize = sz;
@@ -157,12 +152,10 @@ ErrorOr<VoidPtr> USER_PROCESS::New(SizeT sz, SizeT pad_amount) {
prev_entry = entry;
- if (entry->Color == kBlackTreeKind) break;
-
if (entry->Child && entry->Child->EntrySize > 0 && entry->Child->EntrySize == sz) {
entry = entry->Child;
is_parent = YES;
- } else if (entry->Next && entry->Child->EntrySize > 0 && entry->Next->EntrySize == sz) {
+ } else if (entry->Next && entry->Next->EntrySize > 0 && entry->Next->EntrySize == sz) {
is_parent = NO;
entry = entry->Next;
} else {
@@ -173,6 +166,11 @@ ErrorOr<VoidPtr> USER_PROCESS::New(SizeT sz, SizeT pad_amount) {
auto new_entry = new PROCESS_HEAP_TREE<VoidPtr>();
+ if (!new_entry) {
+ this->Crash();
+ return ErrorOr<VoidPtr>(-kErrorHeapOutOfMemory);
+ }
+
new_entry->Entry = ptr;
new_entry->EntrySize = sz;
new_entry->EntryPad = pad_amount;
@@ -242,10 +240,13 @@ STATIC Void sched_free_ptr_tree(PROCESS_HEAP_TREE<VoidPtr>* memory_ptr_list) {
auto next = memory_ptr_list->Next;
- mm_free_ptr(memory_ptr_list);
+ if (next->Child) sched_free_ptr_tree(next->Child);
+
+ memory_ptr_list->Child = nullptr;
- if (memory_ptr_list->Child) sched_free_ptr_tree(memory_ptr_list->Child);
+ mm_free_ptr(memory_ptr_list);
+ memory_ptr_list = nullptr;
memory_ptr_list = next;
}
}
@@ -262,18 +263,13 @@ Void USER_PROCESS::Exit(const Int32& exit_code) {
this->LastExitCode = exit_code;
this->UTime = 0;
- kLastExitCode = exit_code;
-
- --this->ParentTeam->mProcessCur;
-
- auto memory_ptr_list = this->HeapTree;
-
#ifdef __NE_VIRTUAL_MEMORY_SUPPORT__
auto pd = kKernelVM;
hal_write_cr3(this->VMRegister);
#endif
- sched_free_ptr_tree(memory_ptr_list);
+ sched_free_ptr_tree(this->HeapTree);
+ this->HeapTree = nullptr;
#ifdef __NE_VIRTUAL_MEMORY_SUPPORT__
hal_write_cr3(pd);
@@ -322,7 +318,7 @@ Void USER_PROCESS::Exit(const Int32& exit_code) {
/***********************************************************************************/
Bool USER_PROCESS::SpawnDylib() {
- // React according to process kind.
+ // React according to the process's kind.
switch (this->Kind) {
case USER_PROCESS::kExecutableDylibKind: {
this->DylibDelegate = rtl_init_dylib_pef(*this);
@@ -338,11 +334,15 @@ Bool USER_PROCESS::SpawnDylib() {
return NO;
}
default: {
- (Void)(kout << "Unknown process kind: " << hex_number(this->Kind) << kendl);
- this->Crash();
- return NO;
+ break;
}
}
+
+ (Void)(kout << "Unknown process kind: " << hex_number(this->Kind) << kendl);
+ this->Crash();
+ return NO;
+
+ return NO;
}
/***********************************************************************************/
@@ -507,11 +507,11 @@ SizeT UserProcessScheduler::Run() noexcept {
// We add a bigger cooldown according to the RTime and affinity here.
if (process.PTime < process.RTime && AffinityKind::kRealTime != process.Affinity) {
if (process.RTime < (Int32) AffinityKind::kVeryHigh)
- process.RTime = (Int32) AffinityKind::kLowUsage / 2;
+ process.RTime += (Int32) AffinityKind::kLowUsage;
else if (process.RTime < (Int32) AffinityKind::kHigh)
- process.RTime = (Int32) AffinityKind::kStandard / 3;
+ process.RTime += (Int32) AffinityKind::kStandard;
else if (process.RTime < (Int32) AffinityKind::kStandard)
- process.RTime = (Int32) AffinityKind::kHigh / 4;
+ process.RTime += (Int32) AffinityKind::kHigh;
process.PTime -= process.RTime;
process.RTime = 0UL;
diff --git a/dev/libSystem/SystemKit/System.h b/dev/libSystem/SystemKit/System.h
index 91899efe..421868ae 100644
--- a/dev/libSystem/SystemKit/System.h
+++ b/dev/libSystem/SystemKit/System.h
@@ -309,16 +309,20 @@ IMPORT_C SInt32 PwrSendCode(_Output SInt32& code);
// CD-ROM API.
// ------------------------------------------------------------------------------------------ //
-IMPORT_C SInt32 CdEjectDrive(_Input Char drv_letter);
+#define kCDDevicePath "/devices/dvd{}"
-IMPORT_C SInt32 CdOpenTray(Void);
+IMPORT_C IORef CdOpenTray(Void);
+
+IMPORT_C SInt32 CdEjectDrive(_Input IORef cdrom);
IMPORT_C SInt32 CdCloseTray(Void);
// ------------------------------------------------------------------------------------------ //
-// Printer API.
+// TTY API.
// ------------------------------------------------------------------------------------------ //
+#define kPrintDevicePath "/devices/tty{}"
+
IMPORT_C SInt32 PrintOut(IORef file /* nullptr to direct to stdout */, const Char* fmt, ...);
IMPORT_C SInt32 PrintIn(IORef file /* nullptr to direct to stdout */, const Char* fmt, ...);
diff --git a/dev/libSystem/libSystem.json b/dev/libSystem/libSystem.json
index fdcd2a56..9df1b8f0 100644
--- a/dev/libSystem/libSystem.json
+++ b/dev/libSystem/libSystem.json
@@ -3,7 +3,7 @@
"compiler_std": "c++20",
"headers_path": ["../", "./"],
"sources_path": ["src/*.cc", "src/*.stub.obj"],
- "output_name": "libSystem.sys",
+ "output_name": "libSystem.dll",
"compiler_flags": [
"-ffreestanding",
"-shared",
diff --git a/dev/libSystem/src/Makefile b/dev/libSystem/src/Makefile
index 39af446b..64ef02cc 100644
--- a/dev/libSystem/src/Makefile
+++ b/dev/libSystem/src/Makefile
@@ -1,6 +1,6 @@
##################################################
# (c) Amlal El Mahrouss, all rights reserved.
-# This file is for libSystem.sys's syscall stubs.
+# This file is for libSystem.dll's syscall stubs.
##################################################
ASM=nasm
diff --git a/dev/libSystem/src/SystemImpl.cc b/dev/libSystem/src/SystemAPI.cc
index d0682830..d0682830 100644
--- a/dev/libSystem/src/SystemImpl.cc
+++ b/dev/libSystem/src/SystemAPI.cc
diff --git a/dev/modules/APM/APM.h b/dev/modules/APM/APM.h
index b071a770..29de5114 100644
--- a/dev/modules/APM/APM.h
+++ b/dev/modules/APM/APM.h
@@ -21,15 +21,9 @@ enum {
kAPMPowerCommandReboot = 0x08,
};
-/// @brief Send a APM command into it's own DMA space.
-/// @param base_dma the DMA base address.
-/// @param cmd the command.
-/// @return status code.
-EXTERN_C Int32 apm_send_dma_command(Ptr64 register_addr, APMPowerCmd value);
-
/// @brief Send a APM command into it's own IO space.
/// @param base_dma the IO base port.
/// @param cmd the command.
/// @return status code.
-EXTERN_C Int32 apm_send_io_command(UInt16 cmd, APMPowerCmd value);
+EXTERN_C Int32 apm_send_io_command(UInt16 cmd);
} // namespace Kernel
diff --git a/dev/open_msg/script/window.msg b/dev/open_msg/script/window.msg
deleted file mode 100644
index 77d6ef69..00000000
--- a/dev/open_msg/script/window.msg
+++ /dev/null
@@ -1,6 +0,0 @@
-(window
- :id 1
- :pos (x 100 y 100)
- :size (w 300 h 200)
- :title "My App"
- :on-click (lambda () (log "Clicked!"))) \ No newline at end of file
diff --git a/dev/open_msg/script/window_client.json b/dev/open_msg/script/window_client.json
new file mode 100644
index 00000000..4c8a21ba
--- /dev/null
+++ b/dev/open_msg/script/window_client.json
@@ -0,0 +1,7 @@
+{
+ "id": 1,
+ "pos": { "x": 100, "y": 100 },
+ "size": { "w": 300, "h": 200 },
+ "title": "Window Client",
+ "on-click": "_OnClickCSymbol"
+} \ No newline at end of file