}
extern "C" void int_double_fault(std::uint32_t err_code) {
os::print("Interrupt: Double Fault.\n");
- os::print("Err code: "); os::print(err_code); os::print(".\n");
+ os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
extern "C" void int_coprocessor_segment_overrun() {
}
extern "C" void int_invalid_TSS(std::uint32_t err_code) {
os::print("Interrupt: Invalid TSS.\n");
- os::print("Err code: "); os::print(err_code); os::print(".\n");
+ os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
extern "C" void int_segment_not_present(std::uint32_t err_code) {
os::print("Interrupt: Segment Not Present.\n");
- os::print("Err code: "); os::print(err_code); os::print(".\n");
+ os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
extern "C" void int_stack_segment_fault(std::uint32_t err_code) {
os::print("Interrupt: Stack-Segment Fault.\n");
- os::print("Err code: "); os::print(err_code); os::print(".\n");
+ os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
extern "C" void int_general_protection_fault(std::uint32_t err_code) {
os::print("Interrupt: General Protection Fault.\n");
- os::print("Err code: "); os::print(err_code); os::print(".\n");
+ os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
extern "C" void int_page_fault(std::uint32_t err_code) {
os::print("Interrupt: Page Fault.\n");
- os::print("Err code: "); os::print(err_code); os::print(".\n");
+ os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
extern "C" void int_x87_floating_point_exception() {
}
extern "C" void int_alignment_check(std::uint32_t err_code) {
os::print("Interrupt: Alignment Check.\n");
- os::print("Err code: "); os::print(err_code); os::print(".\n");
+ os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
extern "C" void int_machine_check() {
}
extern "C" void int_control_protection_exception(std::uint32_t err_code) {
os::print("Interrupt: Control Protection Exception.\n");
- os::print("Err code: "); os::print(err_code); os::print(".\n");
+ os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
extern "C" void int_hypervisor_injection_exception() {
}
extern "C" void int_VMM_communication_exception(std::uint32_t err_code) {
os::print("Interrupt: VMM Communication Exception.\n");
- os::print("Err code: "); os::print(err_code); os::print(".\n");
+ os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
extern "C" void int_security_exception(std::uint32_t err_code) {
os::print("Interrupt: Security Exception.\n");
- os::print("Err code: "); os::print(err_code); os::print(".\n");
+ os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
extern "C" void int_default() {
}
break;
case multiboot2::info::type_t::modules:
- os::print(multiboot2::modules_mod_start(it) / 0x1000 * 0x1000);
- os::print("->");
- os::print(multiboot2::modules_mod_end(it) / 0x1000 * 0x1000);
- os::print(": ");
- os::print(multiboot2::modules_string(it));
- os::printc('\n');
+ os::print("{}->{}: {}\n", multiboot2::modules_mod_start(it) / 0x1000 * 0x1000, multiboot2::modules_mod_end(it) / 0x1000 * 0x1000, multiboot2::modules_string(it));
test_module.start_address = os::phys_ptr<os::paging::page>(multiboot2::modules_mod_start(it) / 0x1000 * 0x1000);
test_module.end_address = os::phys_ptr<os::paging::page>(multiboot2::modules_mod_end(it) / 0x1000 * 0x1000); // [s,e], not [s,e[
break;
if (std::uint64_t(virt) >= 0xFFFF'8000'0000'0000) {
return;
}
- os::print(std::uint64_t(virt));
- os::print("->");
- os::print(std::uint64_t(phys.get_phys_addr()));
- os::print(" (");
- os::print(size);
- os::print(")\n");
+ os::print("{}->{} ({})\n", std::uint64_t(virt), std::uint64_t(phys.get_phys_addr()), size);
});
// Allow userspaaaaaaaaace in ring 3. Otherwise, we just immediately page fault.
if (is_empty()) {
os::print("No RAM left.\n");
} else for (auto it = begin(); it != end(); it = it->next) {
- os::print(it.get_phys_addr());
- os::print("->");
- os::print((it + it->size).get_phys_addr());
- os::printc('\n');
+ os::print("{}->{}\n", it.get_phys_addr(), (it + it->size).get_phys_addr());
}
}
void os::printc(char c) {
write_serial(c);
}
-void os::print(const char* format, const char* val) {
- os::assert(format[0] == '\0', "Format string unsupported. TODO.");
+void os::print_formatted(const char* format, const char* val) {
+ os::assert(format[0] == '}', "Format string unsupported. TODO.");
for (std::size_t i = 0; val[i] != '\0'; i++) {
os::printc(val[i]);
}
}
-void os::print(const char* format, std::uint64_t val) {
- os::assert(format[0] == '\0', "Format string unsupported. TODO.");
+void os::print_formatted(const char* format, std::uint64_t val) {
+ os::assert(format[0] == '}', "Format string unsupported. TODO.");
for (int i = 60; i >= 0; i -= 4) {
const int v = (val >> i) & 0xF;
os::printc(v < 10 ? v + '0' : v - 10 + 'a');
}
}
-void os::print(const char* format, std::int64_t val) {
- os::assert(format[0] == '\0', "Format string unsupported. TODO.");
+void os::print_formatted(const char* format, std::int64_t val) {
+ os::assert(format[0] == '}', "Format string unsupported. TODO.");
if (val < 0) {
os::printc('-');
- os::print(format, std::uint64_t(-val));
+ os::print_formatted(format, std::uint64_t(-val));
} else {
os::printc(' ');
- os::print(format, std::uint64_t(val));
+ os::print_formatted(format, std::uint64_t(val));
}
}
-void os::print(const char* format, std::uint32_t val) { os::print(format, std::uint64_t(val)); }
-void os::print(const char* format, std::uint16_t val) { os::print(format, std::uint64_t(val)); }
-void os::print(const char* format, std::uint8_t val) { os::print(format, std::uint64_t(val)); }
-void os::print(const char* format, std::int32_t val) { os::print(format, std::int64_t(val)); }
-void os::print(const char* format, std::int16_t val) { os::print(format, std::int64_t(val)); }
-void os::print(const char* format, std::int8_t val) { os::print(format, std::int64_t(val)); }
+void os::print_formatted(const char* format, std::uint32_t val) { os::print_formatted(format, std::uint64_t(val)); }
+void os::print_formatted(const char* format, std::uint16_t val) { os::print_formatted(format, std::uint64_t(val)); }
+void os::print_formatted(const char* format, std::uint8_t val) { os::print_formatted(format, std::uint64_t(val)); }
+void os::print_formatted(const char* format, std::int32_t val) { os::print_formatted(format, std::int64_t(val)); }
+void os::print_formatted(const char* format, std::int16_t val) { os::print_formatted(format, std::int64_t(val)); }
+void os::print_formatted(const char* format, std::int8_t val) { os::print_formatted(format, std::int64_t(val)); }
void os::assert(bool cond, const char* diagnostic) {
if (!cond) {
- os::print("Error: ");
- os::print(diagnostic);
- os::printc('\n');
+ os::print("Error: {}\n", diagnostic);
os::cli();
while (true) { os::hlt(); }
}
bool serial_transmit_empty();
void write_serial(std::uint8_t v);
+void assert(bool cond, const char* diagnostic);
+
void printc(char c);
-void print(const char* format, const char* val);
-void print(const char* format, std::uint64_t val);
-void print(const char* format, std::int64_t val);
-void print(const char* format, std::uint32_t val);
-void print(const char* format, std::int32_t val);
-void print(const char* format, std::uint16_t val);
-void print(const char* format, std::int16_t val);
-void print(const char* format, std::uint8_t val);
-void print(const char* format, std::int8_t val);
-template <typename T> void print(const T& val) {
- print("", val);
+void print_formatted(const char* format, const char* val);
+void print_formatted(const char* format, std::uint64_t val);
+void print_formatted(const char* format, std::int64_t val);
+void print_formatted(const char* format, std::uint32_t val);
+void print_formatted(const char* format, std::int32_t val);
+void print_formatted(const char* format, std::uint16_t val);
+void print_formatted(const char* format, std::int16_t val);
+void print_formatted(const char* format, std::uint8_t val);
+void print_formatted(const char* format, std::int8_t val);
+
+struct print_nth_helper {
+ std::size_t n;
+ const char* format;
+
+ template <typename T> inline print_nth_helper operator%(const T& v) {
+ if (n == 0) {
+ print_formatted(format, v);
+ return print_nth_helper{std::size_t(-1), format};
+ } else {
+ return print_nth_helper{n - 1, format};
+ }
+ }
+};
+
+template<typename... Ts>
+void print(const char* format, const Ts&... vs) {
+ std::size_t arg_n = 0;
+ for (std::size_t i = 0; format[i] != '\0'; i++) {
+ if (format[i] == '{') {
+ i++;
+ if (format[i] == '\0') {
+ os::assert(false, "Error in format string: unterminated '{}'.");
+ } else if (format[i] == '{') {
+ printc('{');
+ continue;
+ } else {
+ std::size_t format_spec_end = i;
+ while (format[format_spec_end] != '}') {
+ if (format[format_spec_end++] == '\0') {
+ os::assert(false, "Error in format string: unterminated '{}'.");
+ }
+ }
+ std::size_t n = arg_n;
+ if ('0' <= format[i] && format[i] <= '9') {
+ std::size_t n_ = 0;
+ while ('0' <= format[i] && format[i] <= '9') {
+ n_ = n_ * 10 + (format[i++] - '0');
+ }
+ n = n_;
+ }
+ if (format[i] == ':') {
+ i++;
+ } else {
+ os::assert(format[i] == '}', "Error in format string: ':' required before format spec.");
+ }
+ os::assert(n < sizeof...(vs), "Error in format string: not enough arguments.");
+ (print_nth_helper{n, &format[i]} % ... % vs);
+ i = format_spec_end;
+ arg_n++;
+ }
+ } else if (format[i] == '}') {
+ os::assert(format[i + 1] == '}', "Error in format strin: unexpected '}'.");
+ i++;
+ printc('}');
+ } else {
+ printc(format[i]);
+ }
+ }
}
-void assert(bool cond, const char* diagnostic);
}