/** Copyright (C) 2026 Andromeda * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . **/ 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; fn EfiStatus efi_main(EfiHandle image_handle, SystemTable* system_table) @export("efi_main") { 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 \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]; 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 = &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]); }