summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandromeda <andromeda@bsd.my.domain>2026-10-21 23:03:26 -0400
committerandromeda <andromeda@bsd.my.domain>2026-10-21 23:03:26 -0400
commit32ff1b81922209059e474268f2288328f2fac743 (patch)
tree32b5d41e595175429bc8bea26522e9341cb4d3a8
parent4a06a0a7519089caad53f72c8c8c2ebc3592091e (diff)
initial acpi support
-rw-r--r--lib/acpi.c3l/acpi.c3170
-rw-r--r--lib/acpi.c3l/manifest.json9
-rw-r--r--main.c3189
-rw-r--r--project.json4
-rwxr-xr-xscripts/run.sh4
5 files changed, 370 insertions, 6 deletions
diff --git a/lib/acpi.c3l/acpi.c3 b/lib/acpi.c3l/acpi.c3
new file mode 100644
index 0000000..26021dc
--- /dev/null
+++ b/lib/acpi.c3l/acpi.c3
@@ -0,0 +1,170 @@
+module acpi;
+
+import c3os::util;
+
+extern fn int memcmp(void*, void*, usz);
+
+alias Oemid = char[6];
+
+excuse INVALID_DESCRIPTION_HEADER;
+
+enum DescriptionHeaderSignature
+{
+ AEST,
+ AGDI,
+ APIC,
+ APMT,
+ ASPT,
+ BDAT,
+ BERT,
+ BGRT,
+ BOOT,
+ CCEL,
+ CEDT,
+ CPEP,
+ CSRT,
+ DBGP,
+ DBG2,
+ DMAR,
+ DRTM,
+ DSDT,
+ DTPR,
+ ECDT,
+ EINJ,
+ ERST,
+ ETDT,
+ FACP,
+ FACS,
+ FPDT,
+ GTDT,
+ HEST,
+ HPET,
+ IBFT,
+ IERS,
+ IORT,
+ IOVT,
+ IRDT,
+ IVRS,
+ KEYP,
+ LPIT,
+ MCFG,
+ MCHI,
+ MHSP,
+ MISC,
+ MPAM,
+ MPST,
+ MSCT,
+ MSDM,
+ NBFT,
+ NFIT,
+ NHLT,
+ PCCT,
+ PHAT,
+ PMTT,
+ PPTT,
+ PRMT,
+ PSDT,
+ RASF,
+ RAS2,
+ RGRT,
+ RHCT,
+ RIMT,
+ RQSC,
+ RSDT,
+ SBST,
+ SDEI,
+ SDEV,
+ SLIC,
+ SLIT,
+ SPCR,
+ SPMI,
+ SRAT,
+ SSDT,
+ STAO,
+ SVKL,
+ SWFT,
+ TCPA,
+ TPM2,
+ UEFI,
+ WAET,
+ WDAT,
+ WDDT,
+ WDRT,
+ WPBT,
+ WSMT,
+ XENV,
+ XSDT,
+}
+
+$assert(DescriptionHeader::size == 36);
+$assert(RootSystemDescriptionPointer::size == 35);
+struct RootSystemDescriptionPointer @packed
+{
+ char[8] signature;
+ char checksum;
+ Oemid oemid;
+ char revision;
+ uint rsdtAddress;
+ uint length;
+ ExtendedSystemDescriptionTable* xsdtAddress;
+ char[3] _res;
+}
+
+fn bool RootSystemDescriptionPointer.is_valid(&self)
+{
+ if (memcmp(&self.signature, "RSD PTR ", 8) != 0) return false;
+ if (self.revision != 2) return false;
+ char sum = 0;
+ for (int i = 0; i < 20; i++) sum += ((char*)self)[i];
+ if (sum != 0) return false;
+ for (int i = 0; i < RootSystemDescriptionPointer::size; i++) sum += ((char*)self)[i];
+ return (sum == 0);
+}
+
+$assert(ExtendedSystemDescriptionTable::size == 36);
+struct ExtendedSystemDescriptionTable @packed
+{
+ inline DescriptionHeader header;
+ ulong[*] descriptionHeaders;
+}
+
+fn bool ExtendedSystemDescriptionTable.is_valid(&self)
+{
+ if (memcmp(&self.signature, "XSDT", 4) != 0) return false;
+ if (self.revision != 1) return false;
+ char sum = 0;
+ for (uint i = 0; i < self.length; i++) sum += ((char*)self)[i];
+ if (sum != 0) return false;
+ return true;
+}
+
+struct DescriptionHeader @packed
+{
+ char[4] signature;
+ uint length;
+ char revision;
+ char checksum;
+ Oemid oemid;
+ char[8] oemTableId;
+ uint oemRevision;
+ uint creatorId;
+ uint creatorRevision;
+}
+
+fn bool DescriptionHeader.is_valid(&self)
+{
+ if (catch excuse = self.sig()) return false;
+ char sum = 0;
+ for (uint i = 0; i < self.length; i++) sum += ((char*)self)[i];
+ if (sum != 0) return false;
+ return true;
+}
+
+fn DescriptionHeaderSignature? DescriptionHeader.sig(&self)
+{
+ foreach (i, name : DescriptionHeaderSignature::names)
+ {
+ if (memcmp(name, &self.signature, 4) == 0) return (DescriptionHeaderSignature)i;
+ }
+ return INVALID_DESCRIPTION_HEADER~;
+}
diff --git a/lib/acpi.c3l/manifest.json b/lib/acpi.c3l/manifest.json
new file mode 100644
index 0000000..f2a0965
--- /dev/null
+++ b/lib/acpi.c3l/manifest.json
@@ -0,0 +1,9 @@
+{
+ "provides": "acpi",
+ "sources": [
+ "**"
+ ],
+ "targets": {
+ "windows-x64": {}
+ }
+}
diff --git a/main.c3 b/main.c3
index 286b4fe..0e0340b 100644
--- a/main.c3
+++ b/main.c3
@@ -16,7 +16,14 @@
module c3os;
+import acpi;
+
import uefi;
+import uefi::guid;
+import uefi::protocol::mem;
+
+const MDESCS_LEN = 8192;
+macro String version() => "0.1.0";
EfiHandle eh;
SystemTable* st;
@@ -25,19 +32,195 @@ fn EfiStatus efi_main(EfiHandle image_handle, SystemTable* system_table) @export
{
eh = image_handle;
st = system_table;
+ BootServices* bs = st.bootServices;
+
+ util::puts("welcome to c3os version ");
+ util::puts(version());
+ util::puts("\r\n");
+ util::puts("c3os copyright (c) 2026 andromeda <andromeda@galaxious.de>\r\n");
+ util::puts("This program comes with ABSOLUTELY NO WARRANTY.\r\n");
+ util::puts("This is free software, and you are welcome to redistribute it\r\n");
+ util::puts("under certain conditions; see ./LICENSE for details.\r\n");
+
+ log::info("UEFI vendor: ");
+ st.conOut._output_string(st.conOut, st.firmwareVendor);
+ util::puts(" revision ");
+ util::puti(st.firmwareRevision);
+ util::puts("\r\n");
+
+ usz mdescs_len = MDESCS_LEN;
+ MemoryDescriptor[MDESCS_LEN / MemoryDescriptor::size] mdescs = { };
+ usz mdescs_map_key = 0;
+ usz mdescs_descriptor_size = 0;
+ uint mdescs_descriptor_version = 0;
+ bs.get_memory_map(&mdescs_len, &mdescs, &mdescs_map_key, &mdescs_descriptor_size, &mdescs_descriptor_version);
+
+ usz acpi_index;
+ for (usz i = 0; i < st.numberOfTableEntries; i++)
+ {
+ if (guid::@compare(st.configurationTable[i].vendorGuid, guid::ACPI_20_TABLE))
+ {
+ acpi_index = i;
+ }
+ }
+
+ if (acpi_index == 0 || !guid::@compare(st.configurationTable[acpi_index].vendorGuid, guid::ACPI_20_TABLE))
+ {
+ log::fatal("acpi table not found");
+ spin();
+ }
+
+ RootSystemDescriptionPointer* rsdp = st.configurationTable[acpi_index].vendorTable;
+
+ if (!rsdp.is_valid())
+ {
+ log::fatal("checksum verification for root system description pointer failed\r\n");
+ spin();
+ }
+
+ ExtendedSystemDescriptionTable* xsdt = rsdp.xsdtAddress;
+
+ if (!xsdt.is_valid())
+ {
+ log::fatal("checksum verification for extended system description table failed\r\n");
+ spin();
+ }
+
+ uint num_entries = (xsdt.length - ExtendedSystemDescriptionTable::size) / ulong::size;
+
+ for (usz i = 0; i < num_entries; i++)
+ {
+ DescriptionHeader* dh = (DescriptionHeader*)(uptr)xsdt.descriptionHeaders[i];
- st.conOut.@output_string("Hello World!\n");
+ if (dh.is_valid())
+ {
+ log::info("valid signature: ");
+ util::putbs(&dh.signature, 4);
+ util::puts("\r\n");
+ }
+ else
+ {
+ log::info("invalid signature: ");
+ util::putbs(&dh.signature, 4);
+ util::puts("\r\n");
+ }
+ }
+
+ util::puts("done\r\n");
spin();
return SUCCESS;
}
alias PanicFn = fn void(String message, String file, String function, int line);
-PanicFn panicfn = &_panicfn;
-fn void _panicfn(String reason, String file = "", String func = "", int line = 0) => spin();
+PanicFn panicfn = &panic;
+
+fn void panic(String message = "test", String file = "", String function = "", int line = 0)
+{
+ util::puts("PANIC: ");
+ util::puts(message);
+ util::puts("\r\nfunc ");
+ util::puts(function);
+ util::puts(" in file ");
+ util::puts(file);
+ util::puts(" at line ");
+ util::puti((usz)line);
+ util::puts("\r\n");
+ spin();
+}
fn void spin()
{
asm("cli");
asm("hlt");
}
+
+module c3os::log;
+
+import c3os::util;
+
+fn void fatal(String s)
+{
+ util::puts("[fatal]: ");
+ util::puts(s);
+}
+
+fn void info(String s)
+{
+ util::puts("[info]: ");
+ util::puts(s);
+}
+
+fn void warn(String s)
+{
+ util::puts("[warn]: ");
+ util::puts(s);
+}
+
+module c3os::util;
+
+import uefi;
+
+fn int memcmp(void* b1, void* b2, usz len) @export("memcmp") @nostrip
+{
+ for (usz i = 0; i < len; i++)
+ {
+ if (((char*)b1)[i] < ((char*)b2)[i]) return -1;
+ if (((char*)b1)[i] > ((char*)b2)[i]) return 1;
+ }
+ return 0;
+}
+
+fn void* memcpy(void* dst, void* src, usz len) @export("memcpy") @nostrip
+{
+ for (usz i = 0; i < len; i++) ((char*)dst)[i] = ((char*)src)[i];
+ return dst;
+}
+
+fn void* memset(void* b, int c, usz len) @export("memset") @nostrip
+{
+ for (usz i = 0; i < len; i++)
+ {
+ ((char*)b)[i] = (char)c;
+ }
+ return b;
+}
+
+fn void puts(String s) => putbs(s, s.len);
+
+fn void putbs(char[] s, int n)
+{
+ ushort[1024] buf = { };
+ for (int i = 0;; i++)
+ {
+ if (i == n || i == buf.len - 1)
+ {
+ buf[i] = '\0';
+ break;
+ }
+ buf[i] = s[i];
+ }
+ putw((EfiString)&buf);
+}
+
+fn void putw(EfiString w) => c3os::st.conOut._output_string(c3os::st.conOut, w);
+
+fn void puti(usz i)
+{
+ usz place = 1;
+ usz index = 0;
+ ushort[48] buf = { };
+ while (i / place > 0)
+ {
+ buf[buf.len - 2 - index] = '0' + (char)((i / place) % 10);
+ place *= 10;
+ index += 1;
+ }
+ if (i == 0)
+ {
+ buf[buf.len - 2] = '0';
+ index += 1;
+ }
+ buf[buf.len - 1] = '\0';
+ putw((EfiString)&buf[buf.len - 1 - index]);
+}
diff --git a/project.json b/project.json
index fb9305c..ab92cd3 100644
--- a/project.json
+++ b/project.json
@@ -1,7 +1,7 @@
{
"warnings": [ "no-unused" ],
"dependency-search-paths": [ "lib" ],
- "dependencies": [ "uefi" ],
+ "dependencies": [ "acpi", "uefi" ],
"authors": [ "Andromeda <andromeda@galaxious.de>" ],
"version": "0.1.0",
"sources": [ "main.c3" ],
@@ -14,6 +14,8 @@
"extension": ".efi",
"target": "windows-x64",
"no-entry": true,
+ "stack-protector": "none",
+ "stack-probe": "none",
"use-stdlib": false,
"link-libc": false,
"win-subsystem": "efi-app",
diff --git a/scripts/run.sh b/scripts/run.sh
index f2d359c..c09104b 100755
--- a/scripts/run.sh
+++ b/scripts/run.sh
@@ -2,6 +2,7 @@
set -x
+rm -r build
c3c build
mkdir -p ./build/root/EFI/BOOT/
@@ -19,7 +20,6 @@ rm disk.qcow2
vmctl create -s 10G disk.qcow2
qemu-system-x86_64 \
-drive if=pflash,readonly=yes,file=/usr/local/share/qemu/edk2-x86_64-code.fd \
- -cdrom ./build/c3os.iso
-
+ -cdrom ./build/c3os.iso $*
set +x