// SPDX-License-Identifier: GPL-2.0 /* * Author: Huacai Chen * Copyright (C) 2020 Loongson Technology Corporation Limited */ #include #include #include #include #include #include #include #include #include #include #include #define SMBIOS_BIOSSIZE_OFFSET 0x09 #define SMBIOS_BIOSEXTERN_OFFSET 0x13 #define SMBIOS_FREQLOW_OFFSET 0x16 #define SMBIOS_FREQHIGH_OFFSET 0x17 #define SMBIOS_FREQLOW_MASK 0xFF #define SMBIOS_CORE_PACKAGE_OFFSET 0x23 #define LOONGSON_EFI_ENABLE (1 << 3) struct loongson_board_info b_info; static const char dmi_empty_string[] = " "; extern void __init arch_reserve_vmcore(void); extern void __init arch_parse_crashkernel(void); static const char *dmi_string_parse(const struct dmi_header *dm, u8 s) { const u8 *bp = ((u8 *) dm) + dm->length; if (s) { s--; while (s > 0 && *bp) { bp += strlen(bp) + 1; s--; } if (*bp != 0) { size_t len = strlen(bp)+1; size_t cmp_len = len > 8 ? 8 : len; if (!memcmp(bp, dmi_empty_string, cmp_len)) return dmi_empty_string; return bp; } } return ""; } static void __init parse_cpu_table(const struct dmi_header *dm) { long freq_temp = 0; char *dmi_data = (char *)dm; freq_temp = ((*(dmi_data + SMBIOS_FREQHIGH_OFFSET) << 8) + \ ((*(dmi_data + SMBIOS_FREQLOW_OFFSET)) & SMBIOS_FREQLOW_MASK)); cpu_clock_freq = freq_temp * 1000000; loongson_sysconf.cpuname = (void *)dmi_string_parse(dm, dmi_data[16]); loongson_sysconf.cores_per_package = *(dmi_data + SMBIOS_CORE_PACKAGE_OFFSET); pr_info("CpuClock = %llu\n", cpu_clock_freq); } static void __init parse_bios_table(const struct dmi_header *dm) { char *dmi_data = (char *)dm; b_info.bios_size = (*(dmi_data + SMBIOS_BIOSSIZE_OFFSET) + 1) << 6; } static void __init find_tokens(const struct dmi_header *dm, void *dummy) { switch (dm->type) { case 0x0: /* Extern BIOS */ parse_bios_table(dm); break; case 0x4: /* Calling interface */ parse_cpu_table(dm); break; } } static void __init smbios_parse(void) { b_info.bios_vendor = (void *)dmi_get_system_info(DMI_BIOS_VENDOR); b_info.bios_version = (void *)dmi_get_system_info(DMI_BIOS_VERSION); b_info.bios_release_date = (void *)dmi_get_system_info(DMI_BIOS_DATE); b_info.board_vendor = (void *)dmi_get_system_info(DMI_BOARD_VENDOR); b_info.board_name = (void *)dmi_get_system_info(DMI_BOARD_NAME); dmi_walk(find_tokens, NULL); } void __init early_init(void) { init_environ(); efi_init(); memblock_init(); } void __init platform_init(void) { arch_reserve_vmcore(); arch_parse_crashkernel(); #ifdef CONFIG_ACPI_TABLE_UPGRADE acpi_table_upgrade(); #endif #ifdef CONFIG_ACPI acpi_gbl_use_default_register_widths = false; acpi_boot_table_init(); #endif #ifdef CONFIG_NUMA init_numa_memory(); #endif dmi_setup(); smbios_parse(); pr_info("The BIOS Version: %s\n",b_info.bios_version); efi_runtime_init(); register_smp_ops(&loongson3_smp_ops); }