// SPDX-License-Identifier: MPL-2.0 #include "std/stdlib.h" #include "kernel/test.h" #include "kernel/log.h" #include "kernel/conf.h" #include "kernel/efifb.h" #include "cpu/tsc.h" #include "cpu/serial.h" #include "cpu/ap.h" #include "memory/memory.h" #include "irq/tss.h" #include "irq/gdt.h" #include "irq/idt.h" #include "irq/gsi.h" #include "devs/acpi.h" #include "devs/acpi_tables/madt.h" #include "devs/apic/lapic.h" #include "devs/apic/ioapic.h" #include "devs/input/kbd.h" #include "devs/input/ps2.h" char temp[256]; int main() { sh_tsc_init_tsc(); sh_ap_CPU_STRUCT this_cpu_struct; this_cpu_struct.c_entry_point_stack_top_va=0; this_cpu_struct.lapic_id=SH_UINT32_MAX; this_cpu_struct.tss_selector=0; sh_ap_PER_CPU per_cpu; per_cpu.cpu_id=0; per_cpu.bytes_outputed=0; per_cpu.timer_state=SH_FALSE; per_cpu.temp_buffer=temp; per_cpu.temp_buffer_size=256; this_cpu_struct.per_cpu=(&per_cpu); sh_smp_write_gs_base((sh_uint64)&this_cpu_struct); sh_log_string("\n---------------------------\n\n"); sh_log_log("Shelter v0.2",SH_LOG_SOURCE_MAIN); sh_conf_BOOT_CONFIG *boot_config=SH_NULLPTR; SH_STATUS status=sh_conf_get_boot_config(&boot_config); if (status==SH_STATUS_INVALID_SIGNATURE) { sh_log_critical("Boot config doesn't have signature on.",SH_LOG_SOURCE_CONF); sh_log_fatal("Can't obtain boot config.",SH_LOG_SOURCE_MAIN); while (SH_TRUE) {}; } else if (sh_status_error(status)) { sh_log_error("Can't find boot config.",SH_LOG_SOURCE_CONF); sh_log_fatal("Can't obtain boot config.",SH_LOG_SOURCE_MAIN); while (SH_TRUE) {}; } sh_log_log("Obtained boot config.",SH_LOG_SOURCE_CONF); sh_log_log("Loading logging ring buffer setting...",SH_LOG_SOURCE_MAIN); sh_log_load_logging_ring_size(boot_config->log_ring_size); sh_log_log("Loading serial port setting...",SH_LOG_SOURCE_MAIN); sh_log_load_serial_setting(boot_config->log_disable_serial_port); sh_serial_load_serial_port_setting(boot_config->disable_serial_port); sh_log_log("Loading PTP VA...",SH_LOG_SOURCE_MAIN); sh_page_load_boot_ptp_va(boot_config->page_table_pool_va); sh_log_log("Loading log level...",SH_LOG_SOURCE_MAIN); sh_log_load_log_level(boot_config->log_level); sh_log_string("[Shelter:Log @Log] "); sh_log_uint64((sh_uint64)sh_tsc_get_kernel_current_tsc()); sh_log_string(" : Successfully set log level to "); sh_log_uint64((sh_uint64)sh_log_get_log_level()); sh_log_string("\n"); sh_log_flog(SH_LOG_SOURCE_MAIN,"Set logging ring buffer to %2u pages.\n",boot_config->log_ring_size); sh_memory_MEMORY_SERVICES memory_services; status=sh_memory_init_subsystem(boot_config,&memory_services); if (sh_status_error(status)) { sh_log_fatal("Couldn't initialize memory subsystem.",SH_LOG_SOURCE_MAIN); while (SH_TRUE) {}; } sh_log_log("Successfully initialized memory subsystem.",SH_LOG_SOURCE_MAIN); sh_efifb_set_bar(1); sh_tss_TSS tss; status=sh_tss_fill_tss(&tss); if (sh_status_error(status)) { sh_log_ffatal(SH_LOG_SOURCE_MAIN,"Couldn't setup TSS structure. Status: %8s",status); while (1) {}; } sh_log_log("Successfully initialized TSS structure.",SH_LOG_SOURCE_MAIN); sh_gdt_GDT gdt; status=sh_gdt_fill_gdt(&tss,&gdt); if (sh_status_error(status)) { sh_log_fatal("Couldn't setup GDT structure.",SH_LOG_SOURCE_MAIN); while (1) {}; } sh_gdt_load_gdtr(&gdt); sh_gdt_reload_registers(); sh_smp_write_gs_base((sh_uint64)&this_cpu_struct); sh_log_log("Successfully loaded GDT.",SH_LOG_SOURCE_MAIN); sh_tss_load_tr(&tss); sh_log_log("Successfully loaded TSS.",SH_LOG_SOURCE_MAIN); sh_idt_IDT idt; status=sh_idt_fill_idt(&idt); if (sh_status_error(status)) { sh_log_fatal("Couldn't setup IDT structure.",SH_LOG_SOURCE_MAIN); while (1) {}; } sh_log_log("Successfully initialized IDT structure.",SH_LOG_SOURCE_MAIN); sh_idt_load_idtr(&idt); sh_log_log("Successfully loaded IDT.",SH_LOG_SOURCE_MAIN); sh_efifb_set_bar(2); sh_log_log("IDT enabled. Parsing ACPI RSDP...",SH_LOG_SOURCE_MAIN); sh_apci_ACPI_POINTERS_ROOT acpi_pointers_root; status=sh_acpi_parse_rsdp(boot_config->acpi_rsdp,boot_config->acpi_ver,&acpi_pointers_root); if (sh_status_error(status)) { sh_log_ffatal(SH_LOG_SOURCE_MAIN,"Couldn't parse ACPI RSDP. Error code: %8s",status); while (1) {}; } sh_log_log("Parsed ACPI RSDP.",SH_LOG_SOURCE_MAIN); if (acpi_pointers_root.xsdt==0) { sh_log_log("ACPI v1 is being used. It's not supported for the moment.",SH_LOG_SOURCE_MAIN); while (1) {}; } else { sh_log_log("ACPI v2 is being used.",SH_LOG_SOURCE_MAIN); } sh_log_log("Parsing ACPI XSDT...",SH_LOG_SOURCE_MAIN); sh_acpi_ACPI_XSDT_BODY xsdt_body; status=sh_acpi_parse_xsdt(acpi_pointers_root.xsdt,&xsdt_body); if (sh_status_error(status)) { sh_log_ffatal(SH_LOG_SOURCE_MAIN,"Couldn't parse ACPI XSDT. Error code: %8s",status); while (1) {}; } sh_log_log("Parsed ACPI XSDT.",SH_LOG_SOURCE_MAIN); sh_log_log("Parsing ACPI tables...",SH_LOG_SOURCE_MAIN); sh_acpi_ACPI_TABLES acpi_tables; status=sh_acpi_parse_tables(&xsdt_body,&acpi_tables); if (sh_status_error(status)) { sh_log_ffatal(SH_LOG_SOURCE_MAIN,"Couldn't parse ACPI tables. Error code: %8s",status); while (1) {}; } sh_log_log("Parsed ACPI tables.",SH_LOG_SOURCE_MAIN); sh_log_log("Parsing MADT table...",SH_LOG_SOURCE_MAIN); if (acpi_tables.madt_physical_address==0) { sh_log_ffatal(SH_LOG_SOURCE_MAIN,"Didn't found MADT table. Can't continue."); while (1) {}; } status=sh_acpi_madt_parse(acpi_tables.madt_physical_address); if (sh_status_error(status)) { sh_log_ffatal(SH_LOG_SOURCE_MAIN,"Couldn't parse ACPI MADT table. Error code: %8s",status); while (1) {}; } sh_log_log("Parsed MADT table.",SH_LOG_SOURCE_MAIN); sh_efifb_set_bar(3); status=sh_ioapic_mask_all(); if (sh_status_error(status)) { sh_log_fatal("Couldn't disable all IOAPIC GSI lines.",SH_LOG_SOURCE_MAIN); while (SH_TRUE) {}; } sh_log_log("Checking somes flags...",SH_LOG_SOURCE_MAIN); sh_bool has_hypervisor=sh_tsc_has_hypervisor(); if (has_hypervisor) { sh_log_log("Shelter is running on a hypervisor (according to CPUID).",SH_LOG_SOURCE_MAIN); sh_log_warning("This may result in jitter during the CPU frequency estimation.",SH_LOG_SOURCE_MAIN); } else { sh_log_log("Shelter isn't running on a hypervisor (according to CPUID).",SH_LOG_SOURCE_MAIN); } sh_bool constant_tsc=sh_tsc_is_tsc_constant(); if (constant_tsc) { sh_log_log("TSC is constant (according to CPUID).",SH_LOG_SOURCE_MAIN); } else { sh_log_log("TSC isn't constant (according to CPUID).",SH_LOG_SOURCE_MAIN); } sh_uint64 cpu_freq; status=sh_tsc_get_cpu_freq_cpuid(&cpu_freq); if (status==SH_STATUS_UNAVAILABLE) { sh_log_log("CPU frequence from CPUID is unavailable.",SH_LOG_SOURCE_MAIN); } else { sh_log_flog(SH_LOG_SOURCE_MAIN,"CPU frequence from CPUID: %8u hz",cpu_freq); } if (status==SH_STATUS_SUCCESS) { sh_log_log("Using provided CPU frequence by CPUID",SH_LOG_SOURCE_MAIN); } else { sh_log_log("Estimating CPU frequence...",SH_LOG_SOURCE_MAIN); cpu_freq=sh_tsc_estimate_cpu_freq(); sh_log_flog(SH_LOG_SOURCE_MAIN,"Estimated CPU frequence: %8u hz\n",cpu_freq); } sh_tsc_load_cpu_freq(cpu_freq); sh_log_log("Calibrating LAPIC...",SH_LOG_SOURCE_MAIN); sh_lapic_DEVICE *lapic=sh_lapic_get_dev_apic_id(0); if (!lapic) { sh_log_ffatal(SH_LOG_SOURCE_MAIN,"Couldn't get LAPIC."); while (1) {}; } sh_log_flog(SH_LOG_SOURCE_MAIN,"Obtained LAPIC.\n"); status=sh_lapic_init_dev(0xFF,lapic); if (sh_status_error(status)) { sh_log_ffatal(SH_LOG_SOURCE_MAIN,"Couldn't initialize LAPIC."); while (1) {}; } sh_log_flog(SH_LOG_SOURCE_MAIN,"Initialized LAPIC.\n"); status=sh_lapic_calibrate(lapic,cpu_freq); if (sh_status_error(status)) { sh_log_ffatal(SH_LOG_SOURCE_MAIN,"Couldn't calibrate LAPIC."); while (1) {}; } sh_log_flog(SH_LOG_SOURCE_MAIN,"Calibration ended with LAPIC frequency being %8u hz.\n",sh_lapic_get_frequency()); sh_int16 current_cpu=sh_lapic_get_current_core(); if (current_cpu<0) { sh_log_ffatal(SH_LOG_SOURCE_MAIN,"Couldn't obtain current CPU LAPIC id."); while (1) {}; } sh_log_flog(SH_LOG_SOURCE_MAIN,"Current CPU have a LAPIC id of %1u.\n",(sh_uint8)current_cpu); lapic=sh_lapic_get_dev_apic_id((sh_uint64)current_cpu); if (!lapic) { sh_log_ffatal(SH_LOG_SOURCE_MAIN,"Couldn't get LAPIC."); while (1) {}; } sh_log_flog(SH_LOG_SOURCE_MAIN,"Obtained LAPIC of this CPU.\n"); sh_log_log("Preparing application processors initialization...",SH_LOG_SOURCE_MAIN); status=sh_ap_load_gdt_32(); if (sh_status_error(status)) { sh_log_ffatal(SH_LOG_SOURCE_MAIN,"Couldn't generate 32-bits GDT for AP trampoline. Status code: %8s\n",status); while (1) {}; } sh_log_log("Generated 32-bits GDT for AP trampoline.",SH_LOG_SOURCE_MAIN); status=sh_ap_prepare_for_smp_launch(sh_lapic_get_by_apic_id_array(),sh_lapic_get_max_apic_id(),sh_lapic_get_lapic_count(),boot_config,&idt); if (sh_status_error(status)) { sh_log_ffatal(SH_LOG_SOURCE_MAIN,"Couldn't prepare for AP launch. Status code: %8s\n",status); while (1) {}; } sh_log_log("Succesfully prepared for AP launch.",SH_LOG_SOURCE_MAIN); status=sh_ap_start_ap_boot_procedure(boot_config); if (sh_status_error(status)) { sh_printf(SH_FATAL,"Couldn't start AP boot procedure. Status code: %8s\n",status); while (1) {}; } sh_print(SH_LOG,"Succesfully started all APs.\n"); status=sh_gsi_irq_switch(); if (sh_status_error(status)) { sh_printf(SH_FATAL,"Couldn't switch legacy IRQ management to IOAPIC. Status code: %8s\n",status); while (1) {}; } sh_printf(SH_LOG,"Succesfully switched legacy IRQ management to IOAPIC.\n"); sh_efifb_set_bar(4); if (boot_config->test_benchmark) { status=sh_test_benchmark_queues(); if (status!=SH_STATUS_SUCCESS) { sh_print(SH_FATAL,"Couldn't benchmark keyboard events queues.\n"); while (SH_TRUE) {}; } } status=sh_kbd_init_devs(); if (sh_status_error(status)) { sh_printf(SH_FATAL,"Couldn't initialized keyboard subsystem. Status code: %8s\n",status); while (1) {}; } sh_printf(SH_LOG,"Succesfully initialized keyboard subsystem.\n"); status=sh_ps2_driver_init(); if (sh_status_error(status)) { sh_printf(SH_FATAL,"Couldn't initialized PS2 driver. Status code: %8s\n",status); while (1) {}; } sh_printf(SH_LOG,"Succesfully initialized PS2 driver.\n"); status=sh_ps2_disable_scanning(); if (sh_status_error(status)) { sh_printf(SH_FATAL,"Couldn't disable PS2 scanning. Status code: %8s\n",status); while (1) {}; } sh_printf(SH_LOG,"Succesfully disabled PS2 scanning.\n"); sh_efifb_set_bar(5); sh_efifb_set_bar(100); while (1) {}; return 0; }