brintos

brintos / linux-shallow public Read only

0
0
Text · 2.2 KiB · f66f33c Raw
99 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2020 Western Digital Corporation or its affiliates.4 */5 6#include <linux/efi.h>7#include <linux/libfdt.h>8 9#include <asm/efi.h>10#include <linux/unaligned.h>11 12#include "efistub.h"13 14typedef void __noreturn (*jump_kernel_func)(unsigned long, unsigned long);15 16static unsigned long hartid;17 18static int get_boot_hartid_from_fdt(void)19{20	const void *fdt;21	int chosen_node, len;22	const void *prop;23 24	fdt = get_efi_config_table(DEVICE_TREE_GUID);25	if (!fdt)26		return -EINVAL;27 28	chosen_node = fdt_path_offset(fdt, "/chosen");29	if (chosen_node < 0)30		return -EINVAL;31 32	prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid", &len);33	if (!prop)34		return -EINVAL;35 36	if (len == sizeof(u32))37		hartid = (unsigned long) fdt32_to_cpu(*(fdt32_t *)prop);38	else if (len == sizeof(u64))39		hartid = (unsigned long) fdt64_to_cpu(__get_unaligned_t(fdt64_t, prop));40	else41		return -EINVAL;42 43	return 0;44}45 46static efi_status_t get_boot_hartid_from_efi(void)47{48	efi_guid_t boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID;49	struct riscv_efi_boot_protocol *boot_protocol;50	efi_status_t status;51 52	status = efi_bs_call(locate_protocol, &boot_protocol_guid, NULL,53			     (void **)&boot_protocol);54	if (status != EFI_SUCCESS)55		return status;56	return efi_call_proto(boot_protocol, get_boot_hartid, &hartid);57}58 59efi_status_t check_platform_features(void)60{61	efi_status_t status;62	int ret;63 64	status = get_boot_hartid_from_efi();65	if (status != EFI_SUCCESS) {66		ret = get_boot_hartid_from_fdt();67		if (ret) {68			efi_err("Failed to get boot hartid!\n");69			return EFI_UNSUPPORTED;70		}71	}72	return EFI_SUCCESS;73}74 75unsigned long __weak stext_offset(void)76{77	/*78	 * This fallback definition is used by the EFI zboot stub, which loads79	 * the entire image so it can branch via the image header at offset #0.80	 */81	return 0;82}83 84void __noreturn efi_enter_kernel(unsigned long entrypoint, unsigned long fdt,85				 unsigned long fdt_size)86{87	unsigned long kernel_entry = entrypoint + stext_offset();88	jump_kernel_func jump_kernel = (jump_kernel_func)kernel_entry;89 90	/*91	 * Jump to real kernel here with following constraints.92	 * 1. MMU should be disabled.93	 * 2. a0 should contain hartid94	 * 3. a1 should DT address95	 */96	csr_write(CSR_SATP, 0);97	jump_kernel(hartid, fdt);98}99