| /* Copyright (c) 2017-2018, 2020, The Linux Foundation. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "BootLinux.h" |
| #include "libfdt.h" |
| #include <Library/DebugLib.h> |
| #include <Library/MemoryAllocationLib.h> |
| #include <Library/Rtic.h> |
| #include <Protocol/EFIScm.h> |
| #include <Protocol/scm_sip_interface.h> |
| |
| static VOID |
| TxMpdatatoQhee (UINT64 *MpDataAddr, size_t MpDataSize) |
| { |
| EFI_STATUS Status = EFI_SUCCESS; |
| QCOM_SCM_PROTOCOL *QcomScmProtocol = NULL; |
| UINT64 Parameters[SCM_MAX_NUM_PARAMETERS] = {0}; |
| UINT64 Results[SCM_MAX_NUM_RESULTS] = {0}; |
| UINT64 KernelLoadAddr; |
| HypNotifyRticDtb *HypNotify = (HypNotifyRticDtb *)Parameters; |
| |
| /* Locate QCOM_SCM_PROTOCOL */ |
| Status = gBS->LocateProtocol (&gQcomScmProtocolGuid, NULL, |
| (VOID **)&QcomScmProtocol); |
| if (EFI_ERROR (Status)) { |
| DEBUG ( |
| (EFI_D_ERROR, "Locate SCM Protocol failed, Status = (0x%x)\n", Status)); |
| return; |
| } |
| |
| KernelLoadAddr = SetandGetLoadAddr (NULL, LOAD_ADDR_KERNEL); |
| HypNotify->KernelPhysBase = KernelLoadAddr; |
| HypNotify->DtbAddress = MpDataAddr; |
| HypNotify->DtbSize = MpDataSize; |
| |
| DEBUG ((EFI_D_VERBOSE, "Kernel base address (%x)\n", KernelLoadAddr)); |
| DEBUG ((EFI_D_VERBOSE, "Kernel mode check 32/64: KernelLoadAddr->magic_64 " |
| "(%x) KERNEL64_HDR_MAGIC = %x\n", |
| ((struct kernel64_hdr *)KernelLoadAddr)->magic_64, |
| KERNEL64_HDR_MAGIC)); |
| |
| /* Flush Data cache */ |
| WriteBackInvalidateDataCacheRange ((VOID*)MpDataAddr, MpDataSize); |
| |
| /* Make ScmSipSysCall */ |
| Status = QcomScmProtocol->ScmSipSysCall ( |
| QcomScmProtocol, HYP_NOTIFY_RTIC_DTB_LOCATION, |
| HYP_NOTIFY_RTIC_DTB_LOCATION_PARAM_ID, Parameters, Results); |
| if (EFI_ERROR (Status)) |
| DEBUG ((EFI_D_ERROR, "ScmSipSysCall() failed, Status = (0x%x)\n", Status)); |
| |
| return; |
| } |
| |
| BOOLEAN |
| GetRticDtb (VOID *Dtb) |
| { |
| int RootOffset; |
| const char *RticProp = NULL; |
| const char *MpDataProp = NULL; |
| struct RticId RticData; |
| int LenRticId; |
| int LenMpData; |
| UINT8 *MpData = NULL; |
| UINT32 i; |
| UINT64 *MpDataAddr; |
| |
| RootOffset = fdt_path_offset (Dtb, "/"); |
| if (RootOffset < 0) |
| return FALSE; |
| |
| /* Get the rtic-id prop from DTB */ |
| RticProp = |
| (const char *)fdt_getprop (Dtb, RootOffset, "qcom,rtic-id", &LenRticId); |
| if (RticProp && (LenRticId > 0) && (!(LenRticId % RTIC_ID_SIZE))) { |
| RticData.Id = fdt32_to_cpu (((struct RticId *)RticProp)->Id); |
| if (RticData.Id != RTIC_ID) |
| return FALSE; |
| |
| } else { |
| DEBUG ( |
| (EFI_D_VERBOSE, |
| "qcom, rtic-id does not exist (or) is (%d) not a multiple of (%d)\n", |
| LenRticId, RTIC_ID_SIZE)); |
| return FALSE; |
| } |
| |
| /* Get the MP data prop from DTB */ |
| MpDataProp = |
| (const char *)fdt_getprop (Dtb, RootOffset, "MP_DATA", &LenMpData); |
| if (!MpDataProp || LenMpData <= 0) { |
| DEBUG ((EFI_D_VERBOSE, "MP_DATA entry not found\n")); |
| return FALSE; |
| } |
| |
| MpData = (UINT8 *)AllocateZeroPool (LenMpData); |
| if (!MpData) { |
| DEBUG ((EFI_D_ERROR, "Failed to allocate memory for MP Data\n")); |
| return FALSE; |
| } |
| |
| /* Extract MP data from DTB */ |
| for (i = 0; i < LenMpData; i++) { |
| MpData[i] = (UINT8)*MpDataProp; |
| MpDataProp += sizeof (UINT8); |
| } |
| |
| MpDataAddr = (UINT64 *)MpData; |
| |
| /* Display the RTIC id and mpdata */ |
| DEBUG ((EFI_D_VERBOSE, "rtic-id (%x)\n", RticData.Id)); |
| for (i = 0; i < LenMpData; i++) |
| DEBUG ((EFI_D_VERBOSE, "MpData : (%x) \n", MpData[i])); |
| |
| DEBUG ((EFI_D_VERBOSE, "Length of MpData (%d)\n", LenMpData)); |
| DEBUG ((EFI_D_VERBOSE, "MpData (%x) \n", MpDataAddr)); |
| |
| TxMpdatatoQhee (MpDataAddr, LenMpData); |
| |
| FreePool (MpData); |
| MpData = NULL; |
| |
| return TRUE; |
| } |