| /** @file UpdateCmdLine.c |
| * |
| * Copyright (c) 2009, Google Inc. |
| * All rights reserved. |
| * |
| * Copyright (c) 2009-2021, 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 <Library/BootLinux.h> |
| #include <Library/PartitionTableUpdate.h> |
| #include <Library/PrintLib.h> |
| #include <LinuxLoaderLib.h> |
| #include <Protocol/EFICardInfo.h> |
| #include <Protocol/EFIChargerEx.h> |
| #include <Protocol/EFIChipInfoTypes.h> |
| #include <Protocol/EFIPmicPon.h> |
| #include <Protocol/Print2.h> |
| |
| #include "AutoGen.h" |
| #include <DeviceInfo.h> |
| #include "UpdateCmdLine.h" |
| #include "Recovery.h" |
| #include "LECmdLine.h" |
| |
| STATIC CONST CHAR8 *DynamicBootDeviceCmdLine = |
| " androidboot.boot_devices=soc/"; |
| STATIC CONST CHAR8 *BootDeviceCmdLine = " androidboot.bootdevice="; |
| |
| STATIC CONST CHAR8 *UsbSerialCmdLine = " androidboot.serialno="; |
| STATIC CONST CHAR8 *AndroidBootMode = " androidboot.mode="; |
| STATIC CONST CHAR8 *LogLevel = " quite"; |
| STATIC CONST CHAR8 *BatteryChgPause = " androidboot.mode=charger"; |
| STATIC CONST CHAR8 *MdtpActiveFlag = " mdtp"; |
| STATIC CONST CHAR8 *AlarmBootCmdLine = " androidboot.alarmboot=true"; |
| STATIC CHAR8 SystemdSlotEnv[] = " systemd.setenv=\"SLOT_SUFFIX=_a\""; |
| |
| /*Send slot suffix in cmdline with which we have booted*/ |
| STATIC CHAR8 *AndroidSlotSuffix = " androidboot.slot_suffix="; |
| STATIC CHAR8 *RootCmdLine = " rootwait ro init="; |
| STATIC CHAR8 *InitCmdline = INIT_BIN; |
| STATIC CHAR8 *SkipRamFs = " skip_initramfs"; |
| |
| /* Display command line related structures */ |
| #define MAX_DISPLAY_CMD_LINE (256 + MAX_DISPLAY_CMDLINE_LEN) |
| STATIC CHAR8 DisplayCmdLine[MAX_DISPLAY_CMD_LINE]; |
| STATIC UINTN DisplayCmdLineLen = sizeof (DisplayCmdLine); |
| |
| #define MAX_DTBO_IDX_STR 64 |
| STATIC CHAR8 *AndroidBootDtboIdx = " androidboot.dtbo_idx="; |
| STATIC CHAR8 *AndroidBootDtbIdx = " androidboot.dtb_idx="; |
| |
| STATIC CONST CHAR8 *AndroidBootForceNormalBoot = |
| " androidboot.force_normal_boot=1"; |
| STATIC CONST CHAR8 *AndroidBootFstabSuffix = |
| " androidboot.fstab_suffix="; |
| STATIC CHAR8 *FstabSuffixEmmc = "emmc"; |
| STATIC CHAR8 *FstabSuffixDefault = "default"; |
| |
| EFI_STATUS |
| TargetPauseForBatteryCharge (BOOLEAN *BatteryStatus) |
| { |
| EFI_STATUS Status = EFI_SUCCESS; |
| EFI_PM_PON_REASON_TYPE PONReason; |
| EFI_QCOM_PMIC_PON_PROTOCOL *PmicPonProtocol; |
| EFI_CHARGER_EX_PROTOCOL *ChgDetectProtocol; |
| BOOLEAN ChgPresent; |
| BOOLEAN WarmRtStatus; |
| BOOLEAN IsColdBoot; |
| |
| /* Determines whether to pause for batter charge, |
| * Serves only performance purposes, defaults to return zero*/ |
| *BatteryStatus = 0; |
| |
| Status = gBS->LocateProtocol (&gChargerExProtocolGuid, NULL, |
| (VOID **)&ChgDetectProtocol); |
| if (Status == EFI_NOT_FOUND) { |
| DEBUG ((EFI_D_VERBOSE, "Charger Protocol is not available.\n")); |
| return EFI_SUCCESS; |
| } else if (EFI_ERROR (Status)) { |
| DEBUG ((EFI_D_ERROR, "Error finding charger protocol: %r\n", Status)); |
| return Status; |
| } |
| |
| /* The new protocol are supported on future chipsets */ |
| if (ChgDetectProtocol->Revision >= CHARGER_EX_REVISION) { |
| Status = ChgDetectProtocol->IsOffModeCharging (BatteryStatus); |
| if (EFI_ERROR (Status)) |
| DEBUG ( |
| (EFI_D_ERROR, "Error getting off mode charging info: %r\n", Status)); |
| |
| return Status; |
| } else { |
| Status = gBS->LocateProtocol (&gQcomPmicPonProtocolGuid, NULL, |
| (VOID **)&PmicPonProtocol); |
| if (EFI_ERROR (Status)) { |
| DEBUG ((EFI_D_ERROR, "Error locating pmic pon protocol: %r\n", Status)); |
| return Status; |
| } |
| |
| /* Passing 0 for PMIC device Index since the protocol infers internally */ |
| Status = PmicPonProtocol->GetPonReason (0, &PONReason); |
| if (EFI_ERROR (Status)) { |
| DEBUG ((EFI_D_ERROR, "Error getting pon reason: %r\n", Status)); |
| return Status; |
| } |
| |
| Status = PmicPonProtocol->WarmResetStatus (0, &WarmRtStatus); |
| if (EFI_ERROR (Status)) { |
| DEBUG ((EFI_D_ERROR, "Error getting warm reset status: %r\n", Status)); |
| return Status; |
| } |
| |
| IsColdBoot = !WarmRtStatus; |
| Status = ChgDetectProtocol->GetChargerPresence (&ChgPresent); |
| if (EFI_ERROR (Status)) { |
| DEBUG ((EFI_D_ERROR, "Error getting charger info: %r\n", Status)); |
| return Status; |
| } |
| |
| DEBUG ((EFI_D_INFO, " PON Reason is %d cold_boot:%d charger path: %d\n", |
| PONReason, IsColdBoot, ChgPresent)); |
| /* In case of fastboot reboot,adb reboot or if we see the power key |
| * pressed we do not want go into charger mode. |
| * fastboot/adb reboot is warm boot with PON hard reset bit set. |
| */ |
| if (IsColdBoot && (!(PONReason.HARD_RESET) && (!(PONReason.KPDPWR)) && |
| (PONReason.PON1 || PONReason.USB_CHG) && (ChgPresent))) { |
| *BatteryStatus = 1; |
| } else { |
| *BatteryStatus = 0; |
| } |
| |
| return Status; |
| } |
| } |
| |
| /** |
| Check battery status |
| @param[out] BatteryPresent The pointer to battry's presence status. |
| @param[out] ChargerPresent The pointer to battry's charger status. |
| @param[out] BatteryVoltage The pointer to battry's voltage. |
| @retval EFI_SUCCESS Check battery status successfully. |
| @retval other Failed to check battery status. |
| **/ |
| STATIC EFI_STATUS |
| TargetCheckBatteryStatus (BOOLEAN *BatteryPresent, |
| BOOLEAN *ChargerPresent, |
| UINT32 *BatteryVoltage) |
| { |
| EFI_STATUS Status = EFI_SUCCESS; |
| EFI_CHARGER_EX_PROTOCOL *ChgDetectProtocol; |
| |
| Status = gBS->LocateProtocol (&gChargerExProtocolGuid, NULL, |
| (void **)&ChgDetectProtocol); |
| if (Status == EFI_NOT_FOUND) { |
| DEBUG ((EFI_D_VERBOSE, "Charger Protocol is not available.\n")); |
| return EFI_SUCCESS; |
| } else if (EFI_ERROR (Status)) { |
| DEBUG ((EFI_D_ERROR, "Error locating charger detect protocol\n")); |
| return EFI_PROTOCOL_ERROR; |
| } |
| |
| Status = ChgDetectProtocol->GetBatteryPresence (BatteryPresent); |
| if (EFI_ERROR (Status)) { |
| /* Not critical. Hence, loglevel priority is low*/ |
| DEBUG ((EFI_D_VERBOSE, "Error getting battery presence: %r\n", Status)); |
| return Status; |
| } |
| |
| Status = ChgDetectProtocol->GetBatteryVoltage (BatteryVoltage); |
| if (EFI_ERROR (Status)) { |
| DEBUG ((EFI_D_ERROR, "Error getting battery voltage: %r\n", Status)); |
| return Status; |
| } |
| |
| Status = ChgDetectProtocol->GetChargerPresence (ChargerPresent); |
| if (EFI_ERROR (Status)) { |
| DEBUG ((EFI_D_ERROR, "Error getting charger presence: %r\n", Status)); |
| return Status; |
| } |
| |
| return Status; |
| } |
| |
| /** |
| Add safeguards such as refusing to flash if the battery levels is lower than |
| the min voltage |
| or bypass if the battery is not present. |
| @param[out] BatteryVoltage The current voltage of battery |
| @retval BOOLEAN The value whether the device is allowed to flash |
| image. |
| **/ |
| BOOLEAN |
| TargetBatterySocOk (UINT32 *BatteryVoltage) |
| { |
| EFI_STATUS Status = EFI_SUCCESS; |
| EFI_CHARGER_EX_PROTOCOL *ChgDetectProtocol = NULL; |
| EFI_CHARGER_EX_FLASH_INFO FlashInfo = {0}; |
| BOOLEAN BatteryPresent = FALSE; |
| BOOLEAN ChargerPresent = FALSE; |
| |
| *BatteryVoltage = 0; |
| Status = gBS->LocateProtocol (&gChargerExProtocolGuid, NULL, |
| (VOID **)&ChgDetectProtocol); |
| if (Status == EFI_NOT_FOUND) { |
| DEBUG ((EFI_D_VERBOSE, "Charger Protocol is not available.\n")); |
| return TRUE; |
| } else if (EFI_ERROR (Status)) { |
| DEBUG ((EFI_D_ERROR, "Error locating charger detect protocol\n")); |
| return FALSE; |
| } |
| |
| /* The new protocol are supported on future chipsets */ |
| if (ChgDetectProtocol->Revision >= CHARGER_EX_REVISION) { |
| Status = ChgDetectProtocol->IsPowerOk ( |
| EFI_CHARGER_EX_POWER_FLASH_BATTERY_VOLTAGE_TYPE, &FlashInfo); |
| if (EFI_ERROR (Status)) { |
| /* But be bypassable where the device doesn't even have a battery */ |
| if (Status == EFI_UNSUPPORTED) |
| return TRUE; |
| |
| DEBUG ((EFI_D_ERROR, "Error getting the info of charger: %r\n", Status)); |
| return FALSE; |
| } |
| |
| *BatteryVoltage = FlashInfo.BattCurrVoltage; |
| if (!(FlashInfo.bCanFlash) || |
| (*BatteryVoltage < FlashInfo.BattRequiredVoltage)) |
| { |
| DEBUG ((EFI_D_ERROR, "Error battery voltage: %d " |
| "Requireed voltage: %d, can flash: %d\n", *BatteryVoltage, |
| FlashInfo.BattRequiredVoltage, FlashInfo.bCanFlash)); |
| return FALSE; |
| } |
| return TRUE; |
| } else { |
| Status = TargetCheckBatteryStatus (&BatteryPresent, &ChargerPresent, |
| BatteryVoltage); |
| if (((Status == EFI_SUCCESS) && |
| (!BatteryPresent || |
| (BatteryPresent && (*BatteryVoltage > BATT_MIN_VOLT)))) || |
| (Status == EFI_UNSUPPORTED)) { |
| return TRUE; |
| } |
| |
| DEBUG ((EFI_D_ERROR, "Error battery check status: %r voltage: %d\n", |
| Status, *BatteryVoltage)); |
| return FALSE; |
| } |
| } |
| |
| STATIC VOID GetDisplayCmdline (VOID) |
| { |
| EFI_STATUS Status; |
| CHAR8 *Src = NULL; |
| UINT32 SrcLen = 0; |
| |
| Status = gRT->GetVariable ((CHAR16 *)L"DisplayPanelConfiguration", |
| &gQcomTokenSpaceGuid, NULL, &DisplayCmdLineLen, |
| DisplayCmdLine); |
| if (Status != EFI_SUCCESS) { |
| DEBUG ((EFI_D_ERROR, "Unable to get Panel Config, %r\n", Status)); |
| } |
| |
| Status = ReadDisplayCmdLine (&Src, &SrcLen); |
| if (Status == EFI_SUCCESS) { |
| AsciiStrCatS (DisplayCmdLine, MAX_DISPLAY_CMD_LINE, Src); |
| } |
| |
| } |
| |
| /* |
| * Returns length = 0 when there is failure. |
| */ |
| UINT32 |
| GetSystemPath (CHAR8 **SysPath, BootInfo *Info) |
| { |
| INT32 Index; |
| UINT32 Lun; |
| CHAR16 PartitionName[MAX_GPT_NAME_SIZE]; |
| Slot CurSlot = GetCurrentSlotSuffix (); |
| CHAR8 LunCharMapping[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; |
| CHAR8 RootDevStr[BOOT_DEV_NAME_SIZE_MAX]; |
| |
| *SysPath = AllocateZeroPool (sizeof (CHAR8) * MAX_PATH_SIZE); |
| if (!*SysPath) { |
| DEBUG ((EFI_D_ERROR, "Failed to allocated memory for System path query\n")); |
| return 0; |
| } |
| |
| if (IsLEVariant () && |
| Info->BootIntoRecovery) { |
| StrnCpyS (PartitionName, MAX_GPT_NAME_SIZE, (CONST CHAR16 *)L"recoveryfs", |
| StrLen ((CONST CHAR16 *)L"recoveryfs")); |
| } else { |
| StrnCpyS (PartitionName, MAX_GPT_NAME_SIZE, (CONST CHAR16 *)L"system", |
| StrLen ((CONST CHAR16 *)L"system")); |
| } |
| |
| /* Append slot info for A/B Variant */ |
| if (Info->MultiSlotBoot && |
| NAND != CheckRootDeviceType ()) { |
| StrnCatS (PartitionName, MAX_GPT_NAME_SIZE, CurSlot.Suffix, |
| StrLen (CurSlot.Suffix)); |
| } |
| |
| Index = GetPartitionIndex (PartitionName); |
| if (Index == INVALID_PTN || Index >= MAX_NUM_PARTITIONS) { |
| DEBUG ((EFI_D_ERROR, "System partition does not exist\n")); |
| FreePool (*SysPath); |
| *SysPath = NULL; |
| return 0; |
| } |
| |
| Lun = GetPartitionLunFromIndex (Index); |
| GetRootDeviceType (RootDevStr, BOOT_DEV_NAME_SIZE_MAX); |
| if (!AsciiStrCmp ("Unknown", RootDevStr)) { |
| FreePool (*SysPath); |
| *SysPath = NULL; |
| return 0; |
| } |
| |
| if (!AsciiStrCmp ("EMMC", RootDevStr)) { |
| AsciiSPrint (*SysPath, MAX_PATH_SIZE, " root=/dev/mmcblk0p%d", Index); |
| } else if (!AsciiStrCmp ("NAND", RootDevStr)) { |
| /* NAND is being treated as GPT partition, hence reduce the index by 1 as |
| * PartitionIndex (0) should be ignored for correct mapping of partition. |
| */ |
| if (IsNANDSquashFsSupport ()) { |
| // The gluebi device that is to be passed to "root=" will be the first one |
| // after all "regular" mtd devices have been populated. |
| UINT32 PartitionCount = 0; |
| UINT32 MtdBlkIndex = 0; |
| GetPartitionCount (&PartitionCount); |
| if (Info->MultiSlotBoot && |
| (StrnCmp ((CONST CHAR16 *)L"_b", CurSlot.Suffix, |
| StrLen (CurSlot.Suffix)) == 0)) |
| MtdBlkIndex = PartitionCount; |
| else |
| MtdBlkIndex = PartitionCount - 1; |
| AsciiSPrint (*SysPath, MAX_PATH_SIZE, |
| " rootfstype=squashfs root=/dev/mtdblock%d ubi.mtd=%d", |
| MtdBlkIndex, (Index - 1)); |
| } else { |
| AsciiSPrint (*SysPath, MAX_PATH_SIZE, |
| " rootfstype=ubifs rootflags=bulk_read root=ubi0:rootfs ubi.mtd=%d", |
| (Index - 1)); |
| } |
| } else if (!AsciiStrCmp ("UFS", RootDevStr)) { |
| AsciiSPrint (*SysPath, MAX_PATH_SIZE, " root=/dev/sd%c%d", |
| LunCharMapping[Lun], |
| GetPartitionIdxInLun (PartitionName, Lun)); |
| } else { |
| DEBUG ((EFI_D_ERROR, "Unknown Device type\n")); |
| FreePool (*SysPath); |
| *SysPath = NULL; |
| return 0; |
| } |
| DEBUG ((EFI_D_VERBOSE, "System Path - %a \n", *SysPath)); |
| |
| return AsciiStrLen (*SysPath); |
| } |
| |
| STATIC |
| EFI_STATUS |
| UpdateCmdLineParams (UpdateCmdLineParamList *Param, |
| CHAR8 **FinalCmdLine) |
| { |
| CONST CHAR8 *Src; |
| CHAR8 *Dst; |
| UINT32 MaxCmdLineLen = Param->CmdLineLen; |
| |
| Dst = AllocateZeroPool (MaxCmdLineLen); |
| if (!Dst) { |
| DEBUG ((EFI_D_ERROR, "CMDLINE: Failed to allocate destination buffer\n")); |
| return EFI_OUT_OF_RESOURCES; |
| } |
| |
| /* Save start ptr for debug print */ |
| *FinalCmdLine = Dst; |
| |
| if (Param->HaveCmdLine) { |
| Src = Param->CmdLine; |
| AsciiStrCpyS (Dst, MaxCmdLineLen, Src); |
| } |
| |
| if (Param->VBCmdLine != NULL) { |
| Src = Param->VBCmdLine; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| } |
| |
| if (Param->BootDevBuf) { |
| Src = Param->BootDeviceCmdLine; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| |
| Src = Param->BootDevBuf; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| |
| Src = Param->AndroidBootFstabSuffix; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| |
| Src = Param->FstabSuffix; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| |
| /* Dynamic partition append boot_devices for super partition */ |
| if (IsDynamicPartitionSupport ()) { |
| Src = DynamicBootDeviceCmdLine; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| |
| Src = Param->BootDevBuf; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| } |
| |
| FreePool (Param->BootDevBuf); |
| Param->BootDevBuf = NULL; |
| } |
| |
| Src = Param->UsbSerialCmdLine; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| Src = Param->StrSerialNum; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| |
| if (Param->FfbmStr && |
| (Param->FfbmStr[0] != '\0')) { |
| Src = Param->AndroidBootMode; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| |
| Src = Param->FfbmStr; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| |
| Src = Param->LogLevel; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| } else if (Param->PauseAtBootUp) { |
| Src = Param->BatteryChgPause; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| } else if (Param->AlarmBoot) { |
| Src = Param->AlarmBootCmdLine; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| } |
| |
| Src = BOOT_BASE_BAND; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| |
| gBS->SetMem (Param->ChipBaseBand, CHIP_BASE_BAND_LEN, 0); |
| AsciiStrnCpyS (Param->ChipBaseBand, CHIP_BASE_BAND_LEN, |
| BoardPlatformChipBaseBand (), |
| (CHIP_BASE_BAND_LEN - 1)); |
| ToLower (Param->ChipBaseBand); |
| Src = Param->ChipBaseBand; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| |
| Src = Param->DisplayCmdLine; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| |
| if (Param->MdtpActive) { |
| Src = Param->MdtpActiveFlag; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| } |
| |
| if (Param->MultiSlotBoot && |
| !IsBootDevImage ()) { |
| /* Slot suffix */ |
| UnicodeStrToAsciiStr (GetCurrentSlotSuffix ().Suffix, |
| Param->SlotSuffixAscii); |
| if (IsSystemdBootslotEnabled ()) { |
| INT32 StrLen = 0; |
| StrLen = AsciiStrLen (SystemdSlotEnv); |
| SystemdSlotEnv[StrLen - 2] = Param->SlotSuffixAscii[1]; |
| Src = Param->SystemdSlotEnv; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| } else { |
| Src = Param->AndroidSlotSuffix; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| Src = Param->SlotSuffixAscii; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| } |
| } |
| |
| if ((IsBuildAsSystemRootImage () && |
| !Param->MultiSlotBoot) || |
| (Param->MultiSlotBoot && |
| !IsBootDevImage ())) { |
| |
| /* Skip Initramfs*/ |
| if (!IsDynamicPartitionSupport () && |
| !Param->Recovery) { |
| Src = Param->SkipRamFs; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| } |
| |
| /* Add root command line */ |
| Src = Param->RootCmdLine; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| |
| /* Add init value*/ |
| Src = Param->InitCmdline; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| } |
| |
| if (Param->DtboIdxStr != NULL) { |
| Src = Param->DtboIdxStr; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| } |
| |
| if (Param->DtbIdxStr != NULL) { |
| Src = Param->DtbIdxStr; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| } |
| |
| if ((IsBuildUseRecoveryAsBoot () && |
| IsDynamicPartitionSupport () && |
| !Param->Recovery) || |
| (!Param->MultiSlotBoot && |
| !IsBuildUseRecoveryAsBoot ()&& |
| (Param->HeaderVersion >= BOOT_HEADER_VERSION_THREE))) { |
| Src = AndroidBootForceNormalBoot; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| } |
| |
| if (Param->LEVerityCmdLine != NULL) { |
| Src = Param->LEVerityCmdLine; |
| AsciiStrCatS (Dst, MaxCmdLineLen, Src); |
| FreePool (Param->LEVerityCmdLine); |
| Param->LEVerityCmdLine = NULL; |
| } |
| |
| return EFI_SUCCESS; |
| } |
| |
| /*Update command line: appends boot information to the original commandline |
| *that is taken from boot image header*/ |
| EFI_STATUS |
| UpdateCmdLine (CONST CHAR8 *CmdLine, |
| CHAR8 *FfbmStr, |
| BOOLEAN Recovery, |
| BOOLEAN AlarmBoot, |
| CONST CHAR8 *VBCmdLine, |
| CHAR8 **FinalCmdLine, |
| UINT32 HeaderVersion) |
| { |
| EFI_STATUS Status; |
| UINT32 CmdLineLen = 0; |
| UINT32 HaveCmdLine = 0; |
| UINT32 PauseAtBootUp = 0; |
| CHAR8 SlotSuffixAscii[MAX_SLOT_SUFFIX_SZ]; |
| BOOLEAN MultiSlotBoot; |
| CHAR8 ChipBaseBand[CHIP_BASE_BAND_LEN]; |
| CHAR8 *BootDevBuf = NULL; |
| BOOLEAN BatteryStatus; |
| CHAR8 StrSerialNum[SERIAL_NUM_SIZE]; |
| BOOLEAN MdtpActive = FALSE; |
| UpdateCmdLineParamList Param = {0}; |
| CHAR8 DtboIdxStr[MAX_DTBO_IDX_STR] = "\0"; |
| CHAR8 DtbIdxStr[MAX_DTBO_IDX_STR] = "\0"; |
| INT32 DtboIdx = INVALID_PTN; |
| INT32 DtbIdx = INVALID_PTN; |
| CHAR8 *LEVerityCmdLine = NULL; |
| UINT32 LEVerityCmdLineLen = 0; |
| CHAR8 RootDevStr[BOOT_DEV_NAME_SIZE_MAX]; |
| |
| Status = BoardSerialNum (StrSerialNum, sizeof (StrSerialNum)); |
| if (Status != EFI_SUCCESS) { |
| DEBUG ((EFI_D_ERROR, "Error Finding board serial num: %x\n", Status)); |
| return Status; |
| } |
| |
| if (CmdLine && CmdLine[0]) { |
| CmdLineLen = AsciiStrLen (CmdLine); |
| HaveCmdLine = 1; |
| } |
| |
| if (FixedPcdGetBool (EnableMdtpSupport)) { |
| Status = IsMdtpActive (&MdtpActive); |
| |
| if (EFI_ERROR (Status)) { |
| DEBUG ((EFI_D_ERROR, "Failed to get activation state for MDTP, " |
| "Status=%r. Considering MDTP as active\n", |
| Status)); |
| MdtpActive = TRUE; |
| } |
| } |
| |
| if (VBCmdLine != NULL) { |
| DEBUG ((EFI_D_VERBOSE, "UpdateCmdLine VBCmdLine present len %d\n", |
| AsciiStrLen (VBCmdLine))); |
| CmdLineLen += AsciiStrLen (VBCmdLine); |
| } |
| |
| if (HaveCmdLine) { |
| if (IsLEVerity ()) { |
| Status = GetLEVerityCmdLine (CmdLine, &LEVerityCmdLine, |
| &LEVerityCmdLineLen); |
| if (Status != EFI_SUCCESS) { |
| DEBUG ((EFI_D_ERROR, "Failed to get LEVerityCmdLine: %r\n", Status)); |
| } |
| CmdLineLen += LEVerityCmdLineLen; |
| } |
| } |
| |
| BootDevBuf = AllocateZeroPool (sizeof (CHAR8) * BOOT_DEV_MAX_LEN); |
| if (BootDevBuf == NULL) { |
| DEBUG ((EFI_D_ERROR, "Boot device buffer: Out of resources\n")); |
| return EFI_OUT_OF_RESOURCES; |
| } |
| |
| Status = GetBootDevice (BootDevBuf, BOOT_DEV_MAX_LEN); |
| if (Status != EFI_SUCCESS) { |
| DEBUG ((EFI_D_ERROR, "Failed to get Boot Device: %r\n", Status)); |
| FreePool (BootDevBuf); |
| BootDevBuf = NULL; |
| } else { |
| CmdLineLen += AsciiStrLen (BootDeviceCmdLine); |
| CmdLineLen += AsciiStrLen (BootDevBuf); |
| if (IsDynamicPartitionSupport ()) { |
| CmdLineLen += AsciiStrLen (DynamicBootDeviceCmdLine); |
| CmdLineLen += AsciiStrLen (BootDevBuf); |
| } |
| } |
| |
| CmdLineLen += AsciiStrLen (UsbSerialCmdLine); |
| CmdLineLen += AsciiStrLen (StrSerialNum); |
| |
| /* Ignore the EFI_STATUS return value as the default Battery Status = 0 and is |
| * not fatal */ |
| TargetPauseForBatteryCharge (&BatteryStatus); |
| |
| if (FfbmStr && FfbmStr[0] != '\0') { |
| CmdLineLen += AsciiStrLen (AndroidBootMode); |
| CmdLineLen += AsciiStrLen (FfbmStr); |
| /* reduce kernel console messages to speed-up boot */ |
| CmdLineLen += AsciiStrLen (LogLevel); |
| } else if (BatteryStatus && |
| IsChargingScreenEnable () && |
| !Recovery) { |
| DEBUG ((EFI_D_INFO, "Device will boot into off mode charging mode\n")); |
| PauseAtBootUp = 1; |
| CmdLineLen += AsciiStrLen (BatteryChgPause); |
| } else if (AlarmBoot) { |
| CmdLineLen += AsciiStrLen (AlarmBootCmdLine); |
| } |
| |
| if (NULL == BoardPlatformChipBaseBand ()) { |
| DEBUG ((EFI_D_ERROR, "Invalid BaseBand String\n")); |
| FreePool (BootDevBuf); |
| BootDevBuf = NULL; |
| return EFI_NOT_FOUND; |
| } |
| |
| CmdLineLen += AsciiStrLen (BOOT_BASE_BAND); |
| CmdLineLen += AsciiStrLen (BoardPlatformChipBaseBand ()); |
| |
| if (MdtpActive) |
| CmdLineLen += AsciiStrLen (MdtpActiveFlag); |
| |
| MultiSlotBoot = PartitionHasMultiSlot ((CONST CHAR16 *)L"boot"); |
| if (MultiSlotBoot && |
| !IsBootDevImage ()) { |
| if (IsSystemdBootslotEnabled ()) { |
| CmdLineLen += AsciiStrLen (SystemdSlotEnv); |
| } else { |
| /* Add additional length for slot suffix */ |
| CmdLineLen += AsciiStrLen (AndroidSlotSuffix) + MAX_SLOT_SUFFIX_SZ; |
| } |
| } |
| |
| if ((IsBuildAsSystemRootImage () && |
| !MultiSlotBoot) || |
| (MultiSlotBoot && |
| !IsBootDevImage ())) { |
| CmdLineLen += AsciiStrLen (RootCmdLine); |
| CmdLineLen += AsciiStrLen (InitCmdline); |
| |
| if (!IsDynamicPartitionSupport () && |
| !Recovery) |
| CmdLineLen += AsciiStrLen (SkipRamFs); |
| } |
| |
| GetDisplayCmdline (); |
| CmdLineLen += AsciiStrLen (DisplayCmdLine); |
| |
| if (!IsLEVariant ()) { |
| DtboIdx = GetDtboIdx (); |
| if (DtboIdx != INVALID_PTN) { |
| AsciiSPrint (DtboIdxStr, sizeof (DtboIdxStr), |
| "%a%d", AndroidBootDtboIdx, DtboIdx); |
| CmdLineLen += AsciiStrLen (DtboIdxStr); |
| } |
| |
| DtbIdx = GetDtbIdx (); |
| if (DtbIdx != INVALID_PTN) { |
| AsciiSPrint (DtbIdxStr, sizeof (DtbIdxStr), |
| "%a%d", AndroidBootDtbIdx, DtbIdx); |
| CmdLineLen += AsciiStrLen (DtbIdxStr); |
| } |
| } |
| |
| if ((IsBuildUseRecoveryAsBoot () && |
| IsDynamicPartitionSupport () && |
| !Recovery) || |
| (!MultiSlotBoot && |
| !IsBuildUseRecoveryAsBoot () && |
| (HeaderVersion >= BOOT_HEADER_VERSION_THREE))) { |
| CmdLineLen += AsciiStrLen (AndroidBootForceNormalBoot); |
| } |
| |
| CmdLineLen += AsciiStrLen (AndroidBootFstabSuffix); |
| GetRootDeviceType (RootDevStr, BOOT_DEV_NAME_SIZE_MAX); |
| if (!AsciiStriCmp (FstabSuffixEmmc, RootDevStr)) { |
| Param.FstabSuffix = FstabSuffixEmmc; |
| } else { |
| Param.FstabSuffix = FstabSuffixDefault; |
| } |
| CmdLineLen += AsciiStrLen (Param.FstabSuffix); |
| Param.AndroidBootFstabSuffix = AndroidBootFstabSuffix; |
| |
| /* 1 extra byte for NULL */ |
| CmdLineLen += 1; |
| |
| Param.Recovery = Recovery; |
| Param.MultiSlotBoot = MultiSlotBoot; |
| Param.AlarmBoot = AlarmBoot; |
| Param.MdtpActive = MdtpActive; |
| Param.CmdLineLen = CmdLineLen; |
| Param.HaveCmdLine = HaveCmdLine; |
| Param.PauseAtBootUp = PauseAtBootUp; |
| Param.StrSerialNum = StrSerialNum; |
| Param.SlotSuffixAscii = SlotSuffixAscii; |
| Param.ChipBaseBand = ChipBaseBand; |
| Param.DisplayCmdLine = DisplayCmdLine; |
| Param.CmdLine = CmdLine; |
| Param.AlarmBootCmdLine = AlarmBootCmdLine; |
| Param.MdtpActiveFlag = MdtpActiveFlag; |
| Param.BatteryChgPause = BatteryChgPause; |
| Param.UsbSerialCmdLine = UsbSerialCmdLine; |
| Param.VBCmdLine = VBCmdLine; |
| Param.LogLevel = LogLevel; |
| Param.BootDeviceCmdLine = BootDeviceCmdLine; |
| Param.AndroidBootMode = AndroidBootMode; |
| Param.BootDevBuf = BootDevBuf; |
| Param.FfbmStr = FfbmStr; |
| Param.AndroidSlotSuffix = AndroidSlotSuffix; |
| Param.SkipRamFs = SkipRamFs; |
| Param.RootCmdLine = RootCmdLine; |
| Param.InitCmdline = InitCmdline; |
| Param.DtboIdxStr = DtboIdxStr; |
| Param.DtbIdxStr = DtbIdxStr; |
| Param.LEVerityCmdLine = LEVerityCmdLine; |
| Param.HeaderVersion = HeaderVersion; |
| Param.SystemdSlotEnv = SystemdSlotEnv; |
| |
| Status = UpdateCmdLineParams (&Param, FinalCmdLine); |
| if (Status != EFI_SUCCESS) { |
| return Status; |
| } |
| |
| DEBUG ((EFI_D_INFO, "Cmdline: %a\n", *FinalCmdLine)); |
| DEBUG ((EFI_D_INFO, "\n")); |
| |
| return EFI_SUCCESS; |
| } |