Merge "QcomModulePkg: rename ffbm-02 string to qmmi for Qmmi mode"
diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c
index 95c3c9f..98b1ca9 100644
--- a/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c
+++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c
@@ -1372,7 +1372,7 @@
if (repIndex == 0)
startLen = lenTest + 1;
- /* if (_maxMode) */
+ if (1 /* _maxMode */)
{
UInt32 lenTest2 = lenTest + 1;
UInt32 limit = lenTest2 + p->numFastBytes;
diff --git a/QcomModulePkg/Application/LinuxLoader/LinuxLoader.c b/QcomModulePkg/Application/LinuxLoader/LinuxLoader.c
old mode 100644
new mode 100755
index 02dac0a..317b5b6
--- a/QcomModulePkg/Application/LinuxLoader/LinuxLoader.c
+++ b/QcomModulePkg/Application/LinuxLoader/LinuxLoader.c
@@ -2,7 +2,7 @@
* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
- * Copyright (c) 2009-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-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:
@@ -42,6 +42,7 @@
#include <Library/PartitionTableUpdate.h>
#include <Library/ShutdownServices.h>
#include <Library/StackCanary.h>
+#include "Library/ThreadStack.h"
#include <Library/HypervisorMvCalls.h>
#include <Library/UpdateCmdLine.h>
@@ -53,36 +54,7 @@
STATIC BOOLEAN BootIntoFastboot = FALSE;
STATIC BOOLEAN BootIntoRecovery = FALSE;
-STATIC VOID* UnSafeStackPtr;
-
-STATIC EFI_STATUS __attribute__ ( (no_sanitize ("safe-stack")))
-AllocateUnSafeStackPtr (VOID)
-{
-
- EFI_STATUS Status = EFI_SUCCESS;
-
- UnSafeStackPtr = AllocateZeroPool (BOOT_LOADER_MAX_UNSAFE_STACK_SIZE);
- if (UnSafeStackPtr == NULL) {
- DEBUG ((EFI_D_ERROR, "Failed to Allocate memory for UnSafeStack \n"));
- Status = EFI_OUT_OF_RESOURCES;
- return Status;
- }
-
- UnSafeStackPtr += BOOT_LOADER_MAX_UNSAFE_STACK_SIZE;
-
- return Status;
-}
-
-//This function is to return the Unsafestack ptr address
-VOID** __attribute__ ( (no_sanitize ("safe-stack")))
-__safestack_pointer_address (VOID)
-{
-
- return (VOID**) &UnSafeStackPtr;
-}
-
// This function is used to Deactivate MDTP by entering recovery UI
-
STATIC EFI_STATUS MdtpDisable (VOID)
{
BOOLEAN MdtpActive = FALSE;
@@ -176,7 +148,8 @@
DEBUG ((EFI_D_VERBOSE, "LinuxLoaderEntry Address: 0x%llx\n",
(UINTN)LinuxLoaderEntry));
- Status = AllocateUnSafeStackPtr ();
+ Status = InitThreadUnsafeStack ();
+
if (Status != EFI_SUCCESS) {
DEBUG ((EFI_D_ERROR, "Unable to Allocate memory for Unsafe Stack: %r\n",
Status));
@@ -318,5 +291,6 @@
stack_guard_update_default:
/*Update stack check guard with defualt value then return*/
__stack_chk_guard = DEFAULT_STACK_CHK_GUARD;
+
return Status;
}
diff --git a/QcomModulePkg/Include/Library/Board.h b/QcomModulePkg/Include/Library/Board.h
index 6f82e63..62e30e6 100644
--- a/QcomModulePkg/Include/Library/Board.h
+++ b/QcomModulePkg/Include/Library/Board.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -47,6 +47,8 @@
#define BIT(x) (1UL << x)
+extern RamPartitionEntry *RamPartitionEntries;
+
typedef enum {
EMMC = 0,
UFS = 1,
@@ -54,12 +56,28 @@
UNKNOWN,
} MemCardType;
+#define DDR_SHIFT 8
+
+#define MB (1024 * 1024UL)
+#define DDR_256MB (256 * MB)
+#define DDR_512MB (512 * MB)
+#define DDR_1024MB (1024 * MB)
+#define DDR_2048MB (2048 * MB)
+
+typedef enum {
+ DDRTYPE_256MB = 1,
+ DDRTYPE_512MB,
+ DDRTYPE_1024MB,
+ DDRTYPE_2048MB,
+} DdrType;
+
struct BoardInfo {
EFI_PLATFORMINFO_PLATFORM_INFO_TYPE PlatformInfo;
UINT32 RawChipId;
CHAR8 ChipBaseBand[EFICHIPINFO_MAX_ID_LENGTH];
EFIChipInfoVersionType ChipVersion;
EFIChipInfoFoundryIdType FoundryId;
+ UINT32 HlosSubType;
};
EFI_STATUS
@@ -93,8 +111,10 @@
UfsGetSetBootLun (UINT32 *UfsBootlun, BOOLEAN IsGet);
BOOLEAN BoardPlatformFusion (VOID);
UINT32 BoardPlatformRawChipId (VOID);
-EFI_STATUS GetRamPartitions (RamPartitionEntry **RamPartitions,
+EFI_STATUS ReadRamPartitions (RamPartitionEntry **RamPartitions,
UINT32 *NumPartitions);
EFI_STATUS GetGranuleSize (UINT32 *MinPasrGranuleSize);
VOID GetPageSize (UINT32 *PageSize);
+EFI_STATUS BoardDdrType (UINT32 *Type);
+UINT32 BoardPlatformHlosSubType (VOID);
#endif
diff --git a/QcomModulePkg/Include/Library/LocateDeviceTree.h b/QcomModulePkg/Include/Library/LocateDeviceTree.h
index b08120a..40f70b0 100644
--- a/QcomModulePkg/Include/Library/LocateDeviceTree.h
+++ b/QcomModulePkg/Include/Library/LocateDeviceTree.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017-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
@@ -70,6 +70,8 @@
#define PMIC_SHIFT_IDX (2)
#define PLATFORM_SUBTYPE_SHIFT_ID (0x18)
#define FOUNDRY_ID_MASK (0x00ff0000)
+#define PLATFORM_SUBTYPE_MASK (0x000000ff)
+#define DDR_MASK (0x00000700)
typedef enum {
NONE_MATCH,
@@ -99,6 +101,7 @@
PMIC_MATCH_EXACT_MODEL_IDX3,
SUBTYPE_DEFAULT_MATCH,
SUBTYPE_EXACT_MATCH,
+ DDR_MATCH,
VARIANT_MATCH,
SOC_MATCH,
MAX_MATCH,
@@ -213,6 +216,7 @@
enum dt_entry_info {
DTB_FOUNDRY = 0,
+ DTB_DDR,
DTB_SOC,
DTB_MAJOR_MINOR,
DTB_PMIC0,
diff --git a/QcomModulePkg/Include/Library/ThreadStack.h b/QcomModulePkg/Include/Library/ThreadStack.h
new file mode 100755
index 0000000..1b12467
--- /dev/null
+++ b/QcomModulePkg/Include/Library/ThreadStack.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 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.
+*/
+
+#ifndef __THREADSTACK_H__
+#define __THREADSTACK_H__
+
+#include "list.h"
+#include <Protocol/EFIKernelInterface.h>
+
+/* Stack address will change frequently, we need record the top adderss and
+ * free it at suitable place.
+ */
+typedef struct _THREAD_STACK_ENTRY {
+ Thread *Thread;
+ VOID *StackBottom;
+ VOID *StackTop;
+}THREAD_STACK_ENTRY;
+
+typedef struct _THREAD_LIST_TABLE {
+ struct list_node Node;
+ struct _THREAD_STACK_ENTRY *ThreadStackEntry;
+}THREAD_STACK_NODE;
+
+EFI_STATUS __attribute__ ( (no_sanitize ("safe-stack")))
+AllocateUnSafeStackPtr (Thread* CurrentThread);
+VOID** __attribute__ ( (no_sanitize ("safe-stack")))
+__safestack_pointer_address (VOID);
+VOID ThreadStackNodeRemove (Thread* CurrentThread);
+VOID ThreadStackReleaseCb (VOID * Arg);
+EFI_STATUS InitThreadUnsafeStack (VOID);
+#endif
diff --git a/QcomModulePkg/Include/Protocol/EFIKernelInterface.h b/QcomModulePkg/Include/Protocol/EFIKernelInterface.h
new file mode 100755
index 0000000..b89fc1f
--- /dev/null
+++ b/QcomModulePkg/Include/Protocol/EFIKernelInterface.h
@@ -0,0 +1,657 @@
+/** @file
+ *
+ * UEFI Protocol interface for SMP scheduler services in UEFI
+ *
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ *
+ * Portions Copyright (c) 2008-2015 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+**/
+
+/*=============================================================================
+ EDIT HISTORY
+
+ when who what, where, why
+ -------- --- -----------------------------------------------------------
+ 10/22/19 md Added API's to support unsafe stack.
+ 01/15/19 yg Add Thread/CPU stat API's
+ 09/15/18 yg Add WDog interface
+ 02/21/18 yg Updated to latest interface
+ 06/14/17 yg Initial version
+
+=============================================================================*/
+
+#include <Uefi.h>
+
+#ifndef ___EFI_KERNEL_PROTOCOL_H__
+#define ___EFI_KERNEL_PROTOCOL_H__
+
+/* External global reference to the Kernel Protocol GUID */
+extern EFI_GUID gEfiKernelProtocolGuid;
+
+/* Protocol GUID definition. { B5062BE7-170B-4A32-BE21-689262FF4399 } */
+#define EFI_KERNEL_PROTOCOL_GUID \
+ { 0xB5062BE7, 0x170B, 0x4A32, { 0xBE, 0x21, 0x68, 0x92, 0x62, 0xFF, 0x43, \
+ 0x99 } }
+
+/*
+ * Document the version changes here
+ * V 1.0
+ * Initial version
+ *
+ * V 1.1
+ * Added API ConfigureInterrupt
+ *
+ * V 1.2
+ * Removed unsupported thread interface API's
+ * Added Power transition notification registration API's
+ *
+ * V 1.3
+ * Added Watchdog interface
+ *
+ * V 1.4
+ * Added Thread level stats API, renamed the ThreadStats to CPU Stats to
+ * correct the reference. Retained old API for backward compatibility
+ * Added Lib version member.
+ *
+ * V 1.5
+ * Add Simple lock API's with recursive lock support
+ *
+ * V 1.6
+ * Add API's to support unsafe stack.
+ *
+ * */
+#define EFI_KERNEL_PROTOCOL_VER_INTR_CONFIG 0x00010001
+#define EFI_KERNEL_PROTOCOL_VER_PWR_NOTIFY 0x00010002
+#define EFI_KERNEL_PROTOCOL_VER_WDOG_INTF 0x00010003
+#define EFI_KERNEL_PROTOCOL_VER_THR_CPU_STATS 0x00010004
+#define EFI_KERNEL_PROTOCOL_VER_LIB_VER_API 0x00010004
+#define EFI_KERNEL_PROTOCOL_VER_LOCK_API 0x00010005
+#define EFI_KERNEL_PROTOCOL_VER_UNSAFE_STACK_APIS 0x00010006
+
+/* Current protocol version */
+#define EFI_KERNEL_PROTOCOL_VERSION EFI_KERNEL_PROTOCOL_VER_UNSAFE_STACK_APIS
+
+/*******************************************************************************
+ *
+ * Interface type definitions
+ *
+ ******************************************************************************/
+
+typedef INT32 KStatus;
+
+#define NO_ERROR (0)
+#define ERR_GENERIC (-1)
+#define ERR_NOT_FOUND (-2)
+#define ERR_NOT_READY (-3)
+#define ERR_NO_MSG (-4)
+#define ERR_NO_MEMORY (-5)
+#define ERR_ALREADY_STARTED (-6)
+#define ERR_NOT_VALID (-7)
+#define ERR_INVALID_ARGS (-8)
+#define ERR_NOT_ENOUGH_BUFFER (-9)
+#define ERR_NOT_SUSPENDED (-10)
+#define ERR_OBJECT_DESTROYED (-11)
+#define ERR_NOT_BLOCKED (-12)
+#define ERR_TIMED_OUT (-13)
+#define ERR_ALREADY_EXISTS (-14)
+#define ERR_CHANNEL_CLOSED (-15)
+#define ERR_OFFLINE (-16)
+#define ERR_NOT_ALLOWED (-17)
+#define ERR_BAD_PATH (-18)
+#define ERR_ALREADY_MOUNTED (-19)
+#define ERR_IO (-20)
+#define ERR_NOT_DIR (-21)
+#define ERR_NOT_FILE (-22)
+#define ERR_RECURSE_TOO_DEEP (-23)
+#define ERR_NOT_SUPPORTED (-24)
+#define ERR_TOO_BIG (-25)
+#define ERR_CANCELLED (-26)
+#define ERR_NOT_IMPLEMENTED (-27)
+#define ERR_CHECKSUM_FAIL (-28)
+#define ERR_CRC_FAIL (-29)
+#define ERR_CMD_UNKNOWN (-30)
+#define ERR_BAD_STATE (-31)
+#define ERR_BAD_LEN (-32)
+#define ERR_BUSY (-33)
+#define ERR_THREAD_DETACHED (-34)
+#define ERR_I2C_NACK (-35)
+#define ERR_ALREADY_EXPIRED (-36)
+#define ERR_OUT_OF_RANGE (-37)
+#define ERR_NOT_CONFIGURED (-38)
+#define ERR_NOT_MOUNTED (-39)
+#define ERR_FAULT (-40)
+#define ERR_NO_RESOURCES (-41)
+#define ERR_BAD_HANDLE (-42)
+#define ERR_ACCESS_DENIED (-43)
+#define ERR_PARTIAL_WRITE (-44)
+
+typedef struct
+{
+ UINT32 PreemptCount;
+ UINT32 BlockedCount;
+ UINT64 PreemptDuration;
+ UINT64 BlockedDuration;
+ UINT64 ActiveDuration;
+ UINT64 SleepDuration;
+}ThreadStats;
+
+typedef struct
+{
+ UINT64 IdleTime;
+ UINT64 LastIdleTimestamp;
+ UINT64 Reschedules;
+ UINT64 ContextSwitches;
+ UINT64 Preempts;
+ UINT64 Yields;
+ UINT64 Interrupts; /* platform code increment this */
+ UINT64 TimerInts; /* timer code increment this */
+ UINT64 Timers; /* timer code increment this */
+ UINT64 RescheduleIpis;
+}CpuSchedStats;
+
+enum PwrTxnType{
+ DevicePwrNone = 0, // None
+ DevicePwrOFF = 1, // Turn the device power OFF
+ DevicePwrON = 2, // Turn the device power ON
+};
+
+typedef VOID (*UnsafeStackCb) (void* Arg);
+
+typedef struct {
+ VOID *unsafe_sp_base;
+ UINT64 unsafe_stack_size;
+ UnsafeStackCb cb;
+ VOID *unsafe_stack_cb_data;
+ VOID *unsafe_stack_top;
+}ThrUnsafeStackIntf;
+/******************************************************************************
+ * Interrupt handler interface
+ *
+ * Note that the interrupt handlers registered should not conflict with
+ * scheduler registered interrupts for PPI, SGI and SPI interrupt vectors
+ *
+ * Handlers execute in ISR context, so only events can be posted with some
+ * restrictions.
+ *
+ ******************************************************************************/
+enum HandlerStatus
+{
+ HANDLER_NO_RESCHEDULE = 0,
+ HANDLER_RESCHEDULE
+};
+
+enum IntrConfig
+{
+ INTR_CONFIG_NONE = 0,
+ INTR_CONFIG_EDGE_TRIGGER = 1,
+ INTR_CONFIG_MAX = 2,
+};
+
+typedef enum HandlerStatus (*IntrHandler)(VOID *Arg);
+
+typedef VOID (*REGISTER_INTR_HANDLER) (UINT32 Vector, IntrHandler Handler,
+ VOID *Arg);
+
+typedef KStatus (*MASK_INTERRUPT) (UINT32 Vector);
+typedef KStatus (*UNMASK_INTERRUPT) (UINT32 Vector);
+typedef KStatus (*CONFIGURE_INTERRUPT) (UINT32 Vector,
+ enum IntrConfig Config, VOID* Arg);
+
+typedef struct {
+ REGISTER_INTR_HANDLER RegisterIntrHandler;
+ MASK_INTERRUPT MaskInterrupt;
+ UNMASK_INTERRUPT UnmaskInterrupt;
+ CONFIGURE_INTERRUPT ConfigureInterrupt;
+} InterruptIntf;
+
+/******************************************************************************
+ *
+ * Scheduler supported Event Services
+ *
+ ******************************************************************************/
+
+/* Rules for Events:
+ * - Events may be signaled from interrupt context *but* the reschedule
+ * parameter must be false in that case.
+ * - Events may not be waited upon from interrupt context.
+ * - Events *without* FLAG_AUTOUNSIGNAL:
+ * - Wake up any waiting threads when signaled.
+ * - Continue to do so (no threads will wait) until unsignaled.
+ * - Events *with* FLAG_AUTOUNSIGNAL:
+ * - If one or more threads are waiting when signaled, one thread will
+ * be woken up and return. The signaled state will not be set.
+ * - If no threads are waiting when signaled, the Event will remain
+ * in the signaled state until a thread attempts to wait (at which
+ * time it will unsignal atomicly and return immediately) or
+ * event_unsignal() is called.
+*/
+
+#define SCHED_EVENT_FLAG_AUTOUNSIGNAL 1
+
+#define SCHED_EVENT_STATE_UNSIGNALED 0
+#define SCHED_EVENT_STATE_SIGNALED 1
+
+struct event;
+typedef struct event Event;
+
+typedef UINT32 TimeDuration;
+
+#ifndef INFINITE_TIME
+#define INFINITE_TIME 0xFFFFFFFF
+#endif
+
+typedef Event* (*EVENT_INIT)(UINT64 Id OPTIONAL, _Bool Initial, UINT32 Flags);
+typedef VOID (*EVENT_DESTROY)(Event *);
+
+typedef _Bool (*EVENT_INITIALIZED)(Event *Evt);
+
+typedef KStatus (*EVENT_WAIT)(Event *Evt);
+typedef KStatus (*EVENT_WAIT_TIMEOUT)(Event *, TimeDuration);
+
+typedef KStatus (*EVENT_SIGNAL)(Event *, _Bool Reschedule);
+typedef KStatus (*EVENT_UNSIGNAL)(Event *Evt);
+
+typedef _Bool (*EVENT_GET_SIGNAL_STATE) (Event *Evt);
+
+typedef struct {
+ EVENT_INIT EventInit;
+ EVENT_DESTROY EventDestroy;
+ EVENT_INITIALIZED EventInitialized;
+ EVENT_WAIT EventWait;
+ EVENT_WAIT_TIMEOUT EventWaitTimeout;
+ EVENT_SIGNAL EventSignal;
+ EVENT_UNSIGNAL EventUnsignal;
+ EVENT_GET_SIGNAL_STATE EventGetSignalState;
+}EventIntf;
+
+/******************************************************************************
+ Mutex
+*******************************************************************************/
+/* Rules for Mutexes:
+ * - Mutexes are only safe to use from thread context.
+ * - Mutexes are non-recursive.
+*/
+struct mutex;
+typedef struct mutex Mutex;
+
+typedef Mutex* (*MUTEX_INIT)(UINT64 Id OPTIONAL);
+typedef VOID (*MUTEX_DESTROY)(Mutex *Mtx);
+
+typedef KStatus (*MUTEX_ACQUIRE)(Mutex *Mtx);
+/* try to acquire the mutex with a timeout value */
+typedef KStatus (*MUTEX_ACQUIRE_TIMEOUT)(Mutex *, TimeDuration);
+
+typedef KStatus (*MUTEX_RELEASE)(Mutex *Mtx);
+
+/* does the current thread hold the mutex? */
+typedef _Bool (*IS_MUTEX_HELD)(Mutex *Mtx);
+
+typedef struct {
+ MUTEX_INIT MutexInit;
+ MUTEX_DESTROY MutexDestroy;
+ MUTEX_ACQUIRE MutexAcquire;
+ MUTEX_ACQUIRE_TIMEOUT MutexAcquireTimeout;
+ MUTEX_RELEASE MutexRelease;
+ IS_MUTEX_HELD IsMutexHeld;
+
+}MutexIntf;
+
+/******************************************************************************
+ Semaphore
+******************************************************************************/
+struct semaphore;
+typedef struct semaphore Semaphore;
+
+typedef Semaphore* (*SEM_INIT)(UINT64 Id OPTIONAL, UINT32 Cnt);
+typedef VOID (*SEM_DESTROY)(Semaphore *);
+
+typedef INT32 (*SEM_POST)(Semaphore *, _Bool Resched);
+typedef KStatus (*SEM_WAIT)(Semaphore *);
+typedef KStatus (*SEM_TRYWAIT)(Semaphore *);
+typedef KStatus (*SEM_TIMEDWAIT)(Semaphore *, TimeDuration);
+
+typedef struct {
+ SEM_INIT SemInit;
+ SEM_DESTROY SemDestroy;
+ SEM_POST SemPost;
+ SEM_WAIT SemWait;
+ SEM_TRYWAIT SemTryWait;
+ SEM_TIMEDWAIT SemTimedWait;
+
+}SemIntf;
+
+/******************************************************************************
+ Spinlock
+******************************************************************************/
+
+struct spinlock;
+typedef struct spinlock Spinlock;
+
+typedef Spinlock* (*SPINLOCK_INIT)(UINT64 Id OPTIONAL);
+typedef _Bool (*SPINLOCK_HELD)(Spinlock*);
+typedef INTN (*SPINLOCK_TRY_LOCK)(Spinlock*);
+typedef VOID (*SPINLOCK_LOCK)(Spinlock*);
+typedef VOID (*SPINLOCK_UNLOCK)(Spinlock*);
+
+typedef struct {
+ SPINLOCK_INIT SpinLockInit;
+ SPINLOCK_HELD SpinLockHeld;
+ SPINLOCK_TRY_LOCK SpinTryLock;
+ SPINLOCK_LOCK SpinLock;
+ SPINLOCK_UNLOCK SpinUnlock;
+
+}SpinlockIntf;
+
+/******************************************************************************
+ Thread
+******************************************************************************/
+
+/* Thread priority */
+#define NUM_PRIORITIES 32
+
+#define LOWEST_PRIORITY 0
+#define HIGHEST_PRIORITY (NUM_PRIORITIES - 1)
+
+#define IDLE_PRIORITY LOWEST_PRIORITY
+
+#define DPC_PRIORITY (NUM_PRIORITIES - 2)
+
+#define LOW_PRIORITY (NUM_PRIORITIES / 4)
+
+#define DEFAULT_PRIORITY (NUM_PRIORITIES / 2)
+
+#define HIGH_PRIORITY ((NUM_PRIORITIES / 4) * 3)
+
+#define UEFI_THREAD_PRIORITY HIGH_PRIORITY
+
+/* stack size */
+#ifdef CUSTOM_DEFAULT_STACK_SIZE
+#define DEFAULT_STACK_SIZE CUSTOM_DEFAULT_STACK_SIZE
+#else
+#define DEFAULT_STACK_SIZE 0x1000
+#endif
+
+struct thread;
+typedef struct thread Thread;
+
+typedef INT32 (*ThreadStartRoutine) (VOID *Arg);
+
+typedef Thread* (*THREAD_CREATE)(const char *Name,
+ ThreadStartRoutine EntryPoint, VOID *Arg, INT32 Priority, UINTN Stack_size);
+typedef KStatus (*THREAD_RESUME)(Thread *);
+typedef VOID (*THREAD_EXIT)(INT32 RetCode);
+
+/* the current thread */
+typedef Thread* (*GET_CURRENT_THREAD)(VOID);
+
+typedef INT32 (*THREAD_GET_CURR_CPU)(Thread*);
+typedef INT32 (*THREAD_GET_PINNED_CPU)(Thread*);
+typedef VOID (*THREAD_SET_PINNED_CPU)(Thread*, INT32 Cpu);
+typedef VOID (*THREAD_SET_NAME)(const char *Name);
+typedef VOID (*THREAD_SET_PRIORITY)(INT32 Priority);
+
+typedef VOID (*THREAD_SLEEP)(TimeDuration Delay);
+
+typedef KStatus (*THREAD_DETACH)(Thread *);
+typedef KStatus (*THREAD_JOIN)(Thread *, INT32 *RetCode,
+ TimeDuration Timeout);
+typedef KStatus (*THREAD_DETACH_AND_RESUME)(Thread *);
+
+typedef ThreadStats* (*THREAD_GET_STATS) (Thread *, ThreadStats* Tsp);
+typedef UINT64 (*THREAD_GET_TIMESTAMP) (VOID);
+
+/* Get thread unsafe stack pointer current */
+typedef VOID** (*THREAD_GET_UNSAFE_SP_CURRENT) (Thread *);
+
+/* Get thread unsafe stack base */
+typedef VOID* (*THREAD_GET_UNSAFE_SP_BASE) (Thread *Thr);
+
+/* Returns size of padding that will be used in unsafe stack for bound check */
+typedef UINT64 (*THREAD_GET_UNSAFE_SP_PADDING_SIZE) (VOID);
+
+/* set thread unsafe stack pointer */
+/* For bound check, allocate unsafe stack of size = required stack size +
+ Padding size
+ Get Padding size by calling ThreadGetUnsafeStackPaddingSize ()
+ In Size parameter pass allocated unsafe stack size */
+
+/* NOTE: Client should pass the memory for unsafe stack and it is the
+ responsibility of client to free up that space. */
+typedef KStatus (*THREAD_SET_THREAD_UNSAFE_SP) (Thread *,
+ ThrUnsafeStackIntf *);
+
+typedef struct {
+ THREAD_CREATE ThreadCreate;
+ THREAD_RESUME ThreadResume;
+ THREAD_EXIT ThreadExit;
+ GET_CURRENT_THREAD GetCurrentThread;
+ THREAD_GET_CURR_CPU ThreadGetCurrCpu;
+ THREAD_GET_PINNED_CPU ThreadGetPinnedCpu;
+ VOID* Reserved3; // Deprecated API filler
+ THREAD_SET_PINNED_CPU ThreadSetPinnedCpu;
+ THREAD_SET_NAME ThreadSetName;
+ THREAD_SET_PRIORITY ThreadSetPriority;
+ THREAD_SLEEP ThreadSleep;
+ THREAD_DETACH ThreadDetach;
+ THREAD_JOIN ThreadJoin;
+ THREAD_DETACH_AND_RESUME ThreadDetachAndResume;
+ VOID* Reserved0; // Deprecated API filler
+ VOID* Reserved1; // Deprecated API filler
+ VOID* Reserved2; // Deprecated API filler
+ VOID* Reserved4; // Deprecated API filler
+ THREAD_GET_TIMESTAMP ThreadGetTimeStamp;
+ THREAD_GET_STATS ThreadGetStats;
+ THREAD_GET_UNSAFE_SP_CURRENT ThreadGetUnsafeSPCurrent;
+ THREAD_GET_UNSAFE_SP_BASE ThreadGetUnsafeSPBase;
+ THREAD_SET_THREAD_UNSAFE_SP ThreadSetUnsafeSP;
+ THREAD_GET_UNSAFE_SP_PADDING_SIZE ThreadGetUnsafeStackPaddingSize;
+
+}ThreadIntf;
+
+/******************************************************************************
+ Timer
+******************************************************************************/
+/* Rules for Timers:
+ * - Timer callbacks occur from interrupt context
+ * - Timers may be programmed or canceled from interrupt or thread context
+ * - Timers may be canceled or reprogrammed from within their callback
+ * - Timers currently are dispatched from a 10ms periodic tick
+*/
+
+struct timer;
+typedef struct timer Timer;
+
+typedef enum HandlerStatus (*TimerCallback) (Timer *Tmr, TimeDuration Now,
+ VOID *Arg);
+
+typedef Timer* (*TIMER_INIT)(VOID);
+typedef VOID (*TIMER_SET_ONESHOT)(Timer *, TimeDuration Delay,
+ TimerCallback Cb, VOID *arg);
+typedef VOID (*TIMER_SET_PERIODIC)(Timer *, TimeDuration Period,
+ TimerCallback Cb, VOID *arg);
+typedef VOID (*TIMER_CANCEL)(Timer *);
+
+
+typedef struct {
+ TIMER_INIT TimerInit;
+ TIMER_SET_ONESHOT TimerSetOneshot;
+ TIMER_SET_PERIODIC TimerSetPeriodic;
+ TIMER_CANCEL CancelTimer;
+
+}TimerIntf;
+
+
+/******************************************************************************
+ MP Cpu
+******************************************************************************/
+
+/*
+ * Active CPU :
+ * Busy CPU :
+ * Idle CPU :
+ *
+ * */
+typedef UINT32 (*MPCORE_GET_MAX_CPU_COUNT) (VOID);
+typedef UINT32 (*MPCORE_GET_AVAIL_CPU_COUNT) (VOID);
+typedef UINT32 (*MPCORE_INIT_DEFERRED_CORES) (UINT32 Cpu_Mask);
+
+typedef UINT32 (*MPCORE_GET_CURR_CPU) (VOID);
+
+typedef UINT32 (*MPCORE_IS_CPU_ACTIVE) (UINT32 Cpu);
+
+typedef UINT32 (*MPCORE_GET_ACTIVE_MASK) (VOID);
+typedef UINT32 (*MPCORE_GET_ONLINE_MASK) (VOID);
+
+typedef VOID (*MPCORE_SHUTDOWN_SCHEDULER) (VOID);
+typedef VOID (*MPCORE_POWER_OFF_CPU) (UINT32 CpuMask);
+typedef VOID (*MPCORE_POWER_ON_CPU) (UINT32 CpuMask);
+
+typedef INT32 (*MPCORE_SLEEP_CPU) (UINT64 DurationMs);
+
+typedef CpuSchedStats* (*MPCORE_GET_CPU_SCHED_STATS) (UINT32 Cpu,
+ CpuSchedStats* Csp);
+
+/* Should be able to receive the power transition notification on any of the
+ * cores
+ * */
+typedef void (*PwrTxnNotifyFn) (enum PwrTxnType Evt, VOID* Arg);
+
+typedef EFI_STATUS (*REGISTER_PWR_TRANSITION_NOTIFY) (PwrTxnNotifyFn CbFn,
+ VOID* Arg);
+typedef EFI_STATUS (*UNREGISTER_PWR_TRANSITION_NOTIFY)
+ (PwrTxnNotifyFn CbFn);
+
+typedef struct {
+ MPCORE_GET_MAX_CPU_COUNT MpcoreGetMaxCpuCount;
+
+ MPCORE_GET_AVAIL_CPU_COUNT MpcoreGetAvailCpuCount;
+
+ MPCORE_INIT_DEFERRED_CORES MpcoreInitDeferredCores;
+
+ MPCORE_GET_CURR_CPU MpcoreGetCurrCpu;
+
+ MPCORE_IS_CPU_ACTIVE MpcoreIsCpuActive;
+
+ MPCORE_GET_ACTIVE_MASK MpcoreGetActiveMask;
+ MPCORE_GET_ONLINE_MASK MpcoreGetOnlineMask;
+
+ MPCORE_SHUTDOWN_SCHEDULER MpcoreShutdownScheduler;
+ MPCORE_POWER_OFF_CPU MpcorePowerOffCpu;
+ MPCORE_POWER_ON_CPU MpcorePowerOnCpu;
+
+ /* Sleep related API's
+ * NOTE: Only supported in Non retail test configuration */
+ MPCORE_SLEEP_CPU MpcoreSleepCpu;
+
+ REGISTER_PWR_TRANSITION_NOTIFY RegisterPwrTransitionNotify;
+ UNREGISTER_PWR_TRANSITION_NOTIFY UnRegisterPwrTransitionNotify;
+
+ MPCORE_GET_CPU_SCHED_STATS MpcoreGetCpuSchedStats;
+
+}MpCpuIntf;
+
+/******************************************************************************
+ Watch Dog
+******************************************************************************/
+
+typedef EFI_STATUS (*WDOG_ENABLE) (VOID);
+typedef VOID (*WDOG_DISABLE) (VOID);
+typedef EFI_STATUS (*WDOG_SET_BITE_TIMEOUT) (UINT32 Timeoutms);
+typedef VOID (*WDOG_FORCE_PET) (VOID);
+typedef VOID (*WDOG_FORCE_BITE) (VOID);
+typedef EFI_STATUS (*WDOG_SET_PET_TIMER_PERIOD) (UINT32 Timeoutms);
+
+typedef struct {
+ WDOG_ENABLE WdogEnable;
+ WDOG_DISABLE WdogDisable;
+ WDOG_SET_BITE_TIMEOUT WdogSetBiteTimeout;
+ WDOG_FORCE_PET WdogForcePet;
+ WDOG_FORCE_BITE WdogFirceBite;
+ WDOG_SET_PET_TIMER_PERIOD WdogSetPetTimerPeriod;
+}WDogIntf;
+
+
+/******************************************************************************
+ Simple and Recursible Locks
+******************************************************************************/
+struct LockType;
+typedef struct LockType LockHandle;
+
+/* Creates a lock instance. If the LockStrID has a valid string name, then
+ * the named lock is created if it already doesn't exist, if the named lock
+ * already exists, the lock created points to the same underlying instance.
+ * The Lock String name should be of length 8 chars or less, if its above 8
+ * it results into error to avoid ambiguity since underlying mutex ID len is
+ * same 8 bytes and it could be pointing to the same instance which may not
+ * be the intended
+ *
+ * The option can be provided to get the lock that is recursive (ie the same
+ * thread can lock it many times and has to unlock the same number of times) */
+typedef EFI_STATUS (*INIT_LOCK) (IN CONST CHAR8 *LockStrID OPTIONAL,
+ OUT LockHandle** LockHandlePtr);
+
+typedef EFI_STATUS (*INIT_RECURSIVE_LOCK)
+ (IN CONST CHAR8 *LockStrID OPTIONAL, OUT LockHandle** LockHandlePtr);
+
+typedef VOID (*DESTROY_LOCK) (LockHandle*);
+typedef VOID (*ACQUIRE_LOCK) (LockHandle*);
+typedef VOID (*RELEASE_LOCK) (LockHandle*);
+
+typedef struct {
+ INIT_LOCK InitLock;
+ INIT_RECURSIVE_LOCK InitRecursiveLock;
+ DESTROY_LOCK DestroyLock;
+ ACQUIRE_LOCK AcquireLock;
+ RELEASE_LOCK ReleaseLock;
+}LockIntf;
+
+/*===========================================================================
+ PROTOCOL INTERFACE
+===========================================================================*/
+
+typedef UINT32 (*GET_LIB_VERSION) (VOID);
+
+/*
+ * Scheduler protocol interface in UEFI. Provides the standard scheduler
+ * services for driver/applications consumption.
+ */
+typedef struct {
+ UINT64 Version;
+ InterruptIntf *Interrupt;
+ TimerIntf *Timer;
+ ThreadIntf *Thread;
+ EventIntf *Event;
+ MutexIntf *Mutex;
+ SemIntf *Sem;
+ SpinlockIntf *Spinlock;
+ MpCpuIntf *MpCpu;
+ WDogIntf *WDog;
+ GET_LIB_VERSION GetLibVersion; // Major [31:16], Minor {15:0]
+ LockIntf *Lock;
+}EFI_KERNEL_PROTOCOL;
+
+extern EFI_KERNEL_PROTOCOL* gKernel;
+
+#endif /* ___EFI_KERNEL_PROTOCOL_H__ */
+
diff --git a/QcomModulePkg/Library/BootLib/Board.c b/QcomModulePkg/Library/BootLib/Board.c
index 7b8329a..bd23263 100644
--- a/QcomModulePkg/Library/BootLib/Board.c
+++ b/QcomModulePkg/Library/BootLib/Board.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -41,7 +41,9 @@
[EMMC] = "EMMC", [UFS] = "UFS", [NAND] = "NAND", [UNKNOWN] = "Unknown",
};
-EFI_STATUS
+RamPartitionEntry *RamPartitionEntries = NULL;
+
+STATIC EFI_STATUS
GetRamPartitions (RamPartitionEntry **RamPartitions, UINT32 *NumPartitions)
{
@@ -80,6 +82,32 @@
}
EFI_STATUS
+ReadRamPartitions (RamPartitionEntry **RamPartitions, UINT32 *NumPartitions)
+{
+ STATIC UINT32 NumPartitionEntries = 0;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (RamPartitionEntries == NULL) {
+ NumPartitionEntries = 0;
+ Status = GetRamPartitions (&RamPartitionEntries, &NumPartitionEntries);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error returned from GetRamPartitions %r\n",
+ Status));
+ return Status;
+ }
+ if (!RamPartitionEntries) {
+ DEBUG ((EFI_D_ERROR, "RamPartitions is NULL\n"));
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ *RamPartitions = RamPartitionEntries;
+ *NumPartitions = NumPartitionEntries;
+
+ return Status;
+}
+
+EFI_STATUS
GetGranuleSize (UINT32 *MinPasrGranuleSize)
{
EFI_STATUS Status = EFI_NOT_FOUND;
@@ -120,15 +148,11 @@
UINT64 SmallestBase;
UINT32 i = 0;
- Status = GetRamPartitions (&RamPartitions, &NumPartitions);
+ Status = ReadRamPartitions (&RamPartitions, &NumPartitions);
if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Error returned from GetRamPartitions %r\n", Status));
+ DEBUG ((EFI_D_ERROR, "Error returned from ReadRamPartitions %r\n", Status));
return Status;
}
- if (!RamPartitions) {
- DEBUG ((EFI_D_ERROR, "RamPartitions is NULL\n"));
- return EFI_NOT_FOUND;
- }
SmallestBase = RamPartitions[0].Base;
for (i = 0; i < NumPartitions; i++) {
if (SmallestBase > RamPartitions[i].Base)
@@ -136,7 +160,6 @@
}
*BaseMemory = SmallestBase;
DEBUG ((EFI_D_INFO, "Memory Base Address: 0x%x\n", *BaseMemory));
- FreePool (RamPartitions);
return Status;
}
@@ -456,6 +479,7 @@
{
EFI_STATUS Status;
EFIChipInfoModemType ModemType;
+ UINT32 DdrType;
Status = GetChipInfo (&platform_board_info, &ModemType);
if (EFI_ERROR (Status))
@@ -465,6 +489,12 @@
if (EFI_ERROR (Status))
return Status;
+ Status = BoardDdrType (&DdrType);
+ if (EFI_ERROR (Status))
+ return Status;
+
+ platform_board_info.HlosSubType = (DdrType << DDR_SHIFT);
+
if (BoardPlatformFusion ()) {
AsciiSPrint ((CHAR8 *)platform_board_info.ChipBaseBand,
CHIP_BASE_BAND_LEN, "%a", CHIP_BASE_BAND_MDM);
@@ -486,6 +516,8 @@
platform_board_info.ChipBaseBand));
DEBUG ((EFI_D_VERBOSE, "Fusion Value : %d\n",
platform_board_info.PlatformInfo.fusion));
+ DEBUG ((EFI_D_VERBOSE, "HLOS SubType : 0x%x\n",
+ platform_board_info.HlosSubType));
return Status;
}
@@ -673,3 +705,41 @@
else
StrHwPlatform[ChipIdValidLen - 1] = '\0';
}
+
+EFI_STATUS BoardDdrType (UINT32 *Type)
+{
+ EFI_STATUS Status;
+ RamPartitionEntry *RamPartitions = NULL;
+ UINT32 i = 0;
+ UINT32 NumPartitions = 0;
+ UINT64 DdrSize = 0;
+
+ Status = ReadRamPartitions (&RamPartitions, &NumPartitions);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error returned from GetRamPartitions %r\n", Status));
+ return Status;
+ }
+
+ for (i = 0; i < NumPartitions; i++) {
+ DdrSize += RamPartitions[i].AvailableLength;
+ }
+ DEBUG ((EFI_D_INFO, "Total DDR Size: 0x%016lx \n", DdrSize));
+
+ *Type = 0;
+ if (DdrSize <= DDR_256MB) {
+ *Type = DDRTYPE_256MB;
+ } else if (DdrSize <= DDR_512MB) {
+ *Type = DDRTYPE_512MB;
+ } else if (DdrSize <= DDR_1024MB) {
+ *Type = DDRTYPE_1024MB;
+ } else if (DdrSize <= DDR_2048MB) {
+ *Type = DDRTYPE_2048MB;
+ }
+
+ return Status;
+}
+
+UINT32 BoardPlatformHlosSubType (VOID)
+{
+ return platform_board_info.HlosSubType;
+}
diff --git a/QcomModulePkg/Library/BootLib/BootLib.inf b/QcomModulePkg/Library/BootLib/BootLib.inf
old mode 100644
new mode 100755
index adfeaf2..486c2fd
--- a/QcomModulePkg/Library/BootLib/BootLib.inf
+++ b/QcomModulePkg/Library/BootLib/BootLib.inf
@@ -68,6 +68,7 @@
LECmdLine.c
HypervisorMvCalls.c
FdtRw.c
+ ThreadStack.c
[Packages]
ArmPkg/ArmPkg.dec
@@ -149,6 +150,7 @@
gQcomScmProtocolGuid
gEfiNandPartiGuidProtocolGuid
gEfiDDRGetInfoProtocolGuid
+ gEfiKernelProtocolGuid
[FixedPcd]
gArmTokenSpaceGuid.PcdSystemMemoryBase
diff --git a/QcomModulePkg/Library/BootLib/FdtRw.c b/QcomModulePkg/Library/BootLib/FdtRw.c
index d9abea1..c5bed06 100644
--- a/QcomModulePkg/Library/BootLib/FdtRw.c
+++ b/QcomModulePkg/Library/BootLib/FdtRw.c
@@ -118,9 +118,13 @@
Node->Next = NodeList;
NodeList = Node;
Node->NodeName = AllocateZeroPool (NameLen + 1);
- CopyMem ((VOID *)Node->NodeName, NodeName, NameLen);
+ if (Node->NodeName) {
+ CopyMem ((VOID *)Node->NodeName, NodeName, NameLen);
- Node->NodeOffset = NodeOffset;
+ Node->NodeOffset = NodeOffset;
+ } else {
+ FdtDeleteNodeList ();
+ }
} else {
FdtDeleteNodeList ();
}
diff --git a/QcomModulePkg/Library/BootLib/LinuxLoaderLib.c b/QcomModulePkg/Library/BootLib/LinuxLoaderLib.c
index 75f9f2f..6dee2b5 100644
--- a/QcomModulePkg/Library/BootLib/LinuxLoaderLib.c
+++ b/QcomModulePkg/Library/BootLib/LinuxLoaderLib.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -47,6 +47,75 @@
#define FILE_INFO_SIZE (SIZE_OF_EFI_FILE_INFO + 256)
STATIC UINT32 TimerFreq, FactormS;
+
+/* Returns 0 if the volume label matches otherwise non zero */
+STATIC UINTN
+CompareVolumeLabel (IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* Fs,
+ IN CHAR8* ReqVolumeName)
+{
+ INT32 CmpResult;
+ UINT32 j;
+ UINT16 VolumeLabel[VOLUME_LABEL_SIZE];
+ EFI_FILE_PROTOCOL *FsVolume = NULL;
+ EFI_STATUS Status;
+ UINTN Size;
+ EFI_FILE_SYSTEM_INFO *FsInfo;
+
+ // Get information about the volume
+ Status = Fs->OpenVolume (Fs, &FsVolume);
+
+ if (Status != EFI_SUCCESS) {
+ return 1;
+ }
+
+ /* Get the Volume name */
+ Size = 0;
+ FsInfo = NULL;
+ Status = FsVolume->GetInfo (FsVolume, &gEfiFileSystemInfoGuid, &Size, FsInfo);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ FsInfo = AllocateZeroPool (Size);
+ Status = FsVolume->GetInfo (FsVolume,
+ &gEfiFileSystemInfoGuid, &Size, FsInfo);
+ if (Status != EFI_SUCCESS) {
+ FreePool (FsInfo);
+ return 1;
+ }
+ }
+
+ if (FsInfo == NULL) {
+ return 1;
+ }
+
+ /* Convert the passed in Volume name to Wide char and upper case */
+ for (j = 0; (j < VOLUME_LABEL_SIZE - 1) && ReqVolumeName[j]; ++j) {
+ VolumeLabel[j] = ReqVolumeName[j];
+
+ if ((VolumeLabel[j] >= 'a') &&
+ (VolumeLabel[j] <= 'z')) {
+ VolumeLabel[j] -= ('a' - 'A');
+ }
+ }
+
+ /* Null termination */
+ VolumeLabel[j] = 0;
+
+ /* Change any lower chars in volume name to upper
+ * (ideally this is not needed) */
+ for (j = 0; (j < VOLUME_LABEL_SIZE - 1) && FsInfo->VolumeLabel[j]; ++j) {
+ if ((FsInfo->VolumeLabel[j] >= 'a') &&
+ (FsInfo->VolumeLabel[j] <= 'z')) {
+ FsInfo->VolumeLabel[j] -= ('a' - 'A');
+ }
+ }
+
+ CmpResult = StrnCmp (FsInfo->VolumeLabel, VolumeLabel, VOLUME_LABEL_SIZE);
+
+ FreePool (FsInfo);
+ FsVolume->Close (FsVolume);
+
+ return CmpResult;
+}
+
/**
Returns a list of BlkIo handles based on required criteria
SelectionAttrib : Bitmask representing the conditions that need
@@ -67,7 +136,7 @@
GetBlkIOHandles (IN UINT32 SelectionAttrib,
IN PartiSelectFilter *FilterData,
OUT HandleInfo *HandleInfoPtr,
- IN OUT UINT32 *MaxBlkIopCnt)
+ IN OUT UINT32* MaxBlkIopCnt)
{
EFI_BLOCK_IO_PROTOCOL *BlkIo;
EFI_HANDLE *BlkIoHandles;
@@ -79,6 +148,7 @@
EFI_DEVICE_PATH_PROTOCOL *DevPathInst;
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
VENDOR_DEVICE_PATH *RootDevicePath;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
UINT32 BlkIoCnt = 0;
EFI_PARTITION_ENTRY *PartEntry;
@@ -119,6 +189,10 @@
Status = gBS->HandleProtocol (BlkIoHandles[i], &gEfiBlockIoProtocolGuid,
(VOID **)&BlkIo);
+ /* Fv volumes will not support Blk I/O protocol */
+ if (Status == EFI_UNSUPPORTED) {
+ continue;
+ }
if (Status != EFI_SUCCESS) {
DEBUG ((EFI_D_ERROR, "Unable to get Filesystem Handle %r\n", Status));
@@ -156,12 +230,9 @@
if ((SelectionAttrib & (BLK_IO_SEL_SELECT_ROOT_DEVICE_ONLY |
BLK_IO_SEL_MATCH_ROOT_DEVICE)) != 0) {
- if (!FilterData || (FilterData->RootDeviceType == NULL)) {
- FreePool (BlkIoHandles);
- BlkIoHandles = NULL;
+ if (!FilterData) {
return EFI_INVALID_PARAMETER;
}
-
/* If this is not the root device that we are looking for, ignore this
* handle */
if (RootDevicePath->Header.Type != HARDWARE_DEVICE_PATH ||
@@ -169,8 +240,9 @@
(RootDevicePath->Header.Length[0] |
(RootDevicePath->Header.Length[1] << 8)) !=
sizeof (VENDOR_DEVICE_PATH) ||
- CompareGuid (FilterData->RootDeviceType, &RootDevicePath->Guid) ==
- FALSE)
+ ((FilterData->RootDeviceType != NULL) &&
+ (CompareGuid (FilterData->RootDeviceType,
+ &RootDevicePath->Guid) == FALSE)))
continue;
}
@@ -206,26 +278,55 @@
/* PartitionDxe implementation should return partition type also */
if ((SelectionAttrib & BLK_IO_SEL_MATCH_PARTITION_TYPE_GUID) != 0) {
GUID *PartiType;
- if (!FilterData || (FilterData->PartitionType == NULL)) {
- FreePool (BlkIoHandles);
- BlkIoHandles = NULL;
+ VOID *Interface;
+
+ if (!FilterData ||
+ FilterData->PartitionType == NULL) {
return EFI_INVALID_PARAMETER;
}
- Status = gBS->HandleProtocol (BlkIoHandles[i], &gEfiPartitionTypeGuid,
- (VOID **)&PartiType);
- if (Status != EFI_SUCCESS)
- continue;
+ Status = gBS->HandleProtocol (BlkIoHandles[i],
+ FilterData->PartitionType,
+ (VOID**)&Interface);
+ if (EFI_ERROR (Status)) {
+ Status = gBS->HandleProtocol (BlkIoHandles[i],
+ &gEfiPartitionTypeGuid,
+ (VOID **)&PartiType);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
- if (CompareGuid (PartiType, FilterData->PartitionType) == FALSE)
- continue;
+ if (CompareGuid (PartiType, FilterData->PartitionType) == FALSE) {
+ continue;
+ }
+ }
}
}
/* If we wanted a particular partition and didn't get the HDD DP,
then this handle is probably not the interested ones */
else if ((SelectionAttrib & BLK_IO_SEL_MATCH_PARTITION_TYPE_GUID) != 0)
- continue;
+ continue;
}
+
+ /* Check if the Filesystem related criteria satisfies */
+ if ((SelectionAttrib & BLK_IO_SEL_SELECT_MOUNTED_FILESYSTEM) != 0) {
+ Status = gBS->HandleProtocol (BlkIoHandles[i],
+ &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if ((SelectionAttrib & BLK_IO_SEL_SELECT_BY_VOLUME_NAME) != 0) {
+ if (!FilterData ||
+ FilterData->VolumeName == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (CompareVolumeLabel (Fs, FilterData->VolumeName) != 0) {
+ continue;
+ }
+ }
+ }
+
/* Check if the Partition name related criteria satisfies */
if ((SelectionAttrib & BLK_IO_SEL_MATCH_PARTITION_LABEL) != 0) {
Status = gBS->HandleProtocol (BlkIoHandles[i], &gEfiPartitionRecordGuid,
@@ -547,7 +648,8 @@
side timeout. So split the image into small writing units to let usb
have chance to champ in and doing work in parallel.
*/
- if (!IsUsbTimerStarted ()) {
+
+ if (!IsFlashSplitNeeded ()) {
WriteUnitSize = DivMsgBufSize;
}
diff --git a/QcomModulePkg/Library/BootLib/LocateDeviceTree.c b/QcomModulePkg/Library/BootLib/LocateDeviceTree.c
index 9b65901..4c0e5cd 100644
--- a/QcomModulePkg/Library/BootLib/LocateDeviceTree.c
+++ b/QcomModulePkg/Library/BootLib/LocateDeviceTree.c
@@ -742,9 +742,10 @@
DEBUG ((EFI_D_VERBOSE, "BoardSubtype = %x, DtSubType = %x\n",
BoardPlatformSubType (), CurDtbInfo->DtPlatformSubtype));
- if (CurDtbInfo->DtPlatformSubtype == BoardPlatformSubType ()) {
+ if ((CurDtbInfo->DtPlatformSubtype & PLATFORM_SUBTYPE_MASK) ==
+ BoardPlatformSubType ()) {
CurDtbInfo->DtMatchVal |= BIT (SUBTYPE_EXACT_MATCH);
- } else if (CurDtbInfo->DtPlatformSubtype == 0) {
+ } else if ((CurDtbInfo->DtPlatformSubtype & PLATFORM_SUBTYPE_MASK) == 0) {
CurDtbInfo->DtMatchVal |= BIT (SUBTYPE_DEFAULT_MATCH);
} else {
DEBUG ((EFI_D_VERBOSE, "subtype-id doesnot match\n"));
@@ -752,6 +753,13 @@
CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
return EFI_NOT_FOUND;
}
+
+ if ((CurDtbInfo->DtPlatformSubtype & DDR_MASK) ==
+ (BoardPlatformHlosSubType() & DDR_MASK)) {
+ CurDtbInfo->DtMatchVal |= BIT (DDR_MATCH);
+ } else {
+ DEBUG ((EFI_D_VERBOSE, "ddr size does not match\n"));
+ }
} else {
DEBUG ((EFI_D_VERBOSE, "qcom,board-id does not exist (or) (%d) "
"is not a multiple of (%d)\n",
@@ -1199,6 +1207,7 @@
platform_dt_absolute_match (struct dt_entry *cur_dt_entry,
struct dt_entry_node *dt_list)
{
+ UINT32 cur_dt_hlos_ddr;
UINT32 cur_dt_hw_platform;
UINT32 cur_dt_hw_subtype;
UINT32 cur_dt_msm_id;
@@ -1212,6 +1221,9 @@
cur_dt_hw_platform = (cur_dt_entry->variant_id & 0x000000ff);
cur_dt_hw_subtype = (cur_dt_entry->board_hw_subtype & 0xff);
+ /* Bits 10:8 contain ddr information */
+ cur_dt_hlos_ddr = (cur_dt_entry->board_hw_subtype & 0x700);
+
/* 1. must match the msm_id, platform_hw_id, platform_subtype and DDR size
* soc, board major/minor, pmic major/minor must less than board info
* 2. find the matched DTB then return 1
@@ -1221,6 +1233,7 @@
if ((cur_dt_msm_id == (BoardPlatformRawChipId () & 0x0000ffff)) &&
(cur_dt_hw_platform == BoardPlatformType ()) &&
(cur_dt_hw_subtype == BoardPlatformSubType ()) &&
+ (cur_dt_hlos_ddr == (BoardPlatformHlosSubType() & 0x700)) &&
(cur_dt_entry->soc_rev <= BoardPlatformChipVersion ()) &&
((cur_dt_entry->variant_id & 0x00ffff00) <=
(BoardTargetId () & 0x00ffff00)) &&
@@ -1287,6 +1300,10 @@
current_info = ((dt_node_tmp1->dt_entry_m->platform_id) & 0x00ff0000);
board_info = BoardPlatformFoundryId () << 16;
break;
+ case DTB_DDR:
+ current_info = ((dt_node_tmp1->dt_entry_m->board_hw_subtype) & 0x700);
+ board_info = (BoardPlatformHlosSubType () & 0x700);
+ break;
case DTB_PMIC_MODEL:
for (i = 0; i < 4; i++) {
current_pmic_model[i] = (dt_node_tmp1->dt_entry_m->pmic_rev[i] & 0xff);
@@ -1328,6 +1345,9 @@
case DTB_FOUNDRY:
current_info = ((dt_node_tmp1->dt_entry_m->platform_id) & 0x00ff0000);
break;
+ case DTB_DDR:
+ current_info = ((dt_node_tmp1->dt_entry_m->board_hw_subtype) & 0x700);
+ break;
case DTB_PMIC_MODEL:
for (i = 0; i < 4; i++) {
current_pmic_model[i] = (dt_node_tmp1->dt_entry_m->pmic_rev[i] & 0xff);
@@ -1515,6 +1535,12 @@
*/
platform_dt_absolute_compat_match (dt_list, DTB_FOUNDRY);
+ /* check DDR type
+ * the DDR type must exact match board DDR tpe, this is compatibility
+ * check, if couldn't find the exact match from DTB, will exact match 0x0.
+ */
+ platform_dt_absolute_compat_match (dt_list, DTB_DDR);
+
/* check PMIC model
* the PMIC model must exact match board PMIC model, this is compatibility
* check, if couldn't find the exact match from DTB, will exact match 0x0.
diff --git a/QcomModulePkg/Library/BootLib/Rtic.c b/QcomModulePkg/Library/BootLib/Rtic.c
index b928bed..62e943e 100644
--- a/QcomModulePkg/Library/BootLib/Rtic.c
+++ b/QcomModulePkg/Library/BootLib/Rtic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* 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
@@ -80,7 +80,6 @@
BOOLEAN
GetRticDtb (VOID *Dtb)
{
- EFI_STATUS Status = EFI_SUCCESS;
int RootOffset;
const char *RticProp = NULL;
const char *MpDataProp = NULL;
@@ -90,7 +89,6 @@
UINT8 *MpData = NULL;
UINT32 i;
UINT64 *MpDataAddr;
- UINT64 BaseMemory = 0;
RootOffset = fdt_path_offset (Dtb, "/");
if (RootOffset < 0)
@@ -133,13 +131,6 @@
}
MpDataAddr = (UINT64 *)MpData;
- Status = BaseMem (&BaseMemory);
- if (Status != EFI_SUCCESS) {
- DEBUG ((EFI_D_ERROR, "Base memory not found!!! Status:%r\n", Status));
- FreePool (MpData);
- MpData = NULL;
- return FALSE;
- }
/* Display the RTIC id and mpdata */
DEBUG ((EFI_D_VERBOSE, "rtic-id (%x)\n", RticData.Id));
diff --git a/QcomModulePkg/Library/BootLib/ShutdownServices.c b/QcomModulePkg/Library/BootLib/ShutdownServices.c
old mode 100644
new mode 100755
index f863226..d9c6e50
--- a/QcomModulePkg/Library/BootLib/ShutdownServices.c
+++ b/QcomModulePkg/Library/BootLib/ShutdownServices.c
@@ -17,6 +17,7 @@
#include "ShutdownServices.h"
+#include <FastbootLib/FastbootCmds.h>
#include <Guid/ArmMpCoreInfo.h>
#include <Guid/FileInfo.h>
#include <Guid/GlobalVariable.h>
@@ -40,6 +41,8 @@
UINT32 DescriptorVersion;
UINTN Pages;
+ WaitForFlashFinished ();
+
MemoryMap = NULL;
MemoryMapSize = 0;
Pages = 0;
@@ -102,6 +105,8 @@
ResetDataType ResetData;
EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ WaitForFlashFinished ();
+
StrnCpyS (ResetData.DataBuffer, ARRAY_SIZE (ResetData.DataBuffer),
(CONST CHAR16 *)STR_RESET_PARAM, ARRAY_SIZE (STR_RESET_PARAM) - 1);
ResetData.Bdata = RebootReason;
@@ -120,6 +125,9 @@
VOID ShutdownDevice (VOID)
{
EFI_STATUS Status = EFI_INVALID_PARAMETER;
+
+ WaitForFlashFinished ();
+
gRT->ResetSystem (EfiResetShutdown, Status, 0, NULL);
/* Flow never comes here and is fatal if it comes here.*/
diff --git a/QcomModulePkg/Library/BootLib/ThreadStack.c b/QcomModulePkg/Library/BootLib/ThreadStack.c
new file mode 100755
index 0000000..77050b0
--- /dev/null
+++ b/QcomModulePkg/Library/BootLib/ThreadStack.c
@@ -0,0 +1,347 @@
+/* Copyright (c) 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 "Library/ThreadStack.h"
+#include <Library/DebugLib.h>
+#include "LinuxLoaderLib.h"
+
+STATIC EFI_KERNEL_PROTOCOL *KernIntf = NULL;
+STATIC VOID* UnSafeStackPtr;
+STATIC BOOLEAN IsMultiStack = TRUE;
+// This is a runtime variable to record if "thread unsafe stack low level" is
+// supported, if TRUE, we can set/get multithread stack by API, if FALSE, we
+// can manage stack by link table.
+STATIC BOOLEAN IsThreadUSSLLSupported = FALSE;
+STATIC THREAD_STACK_NODE * ThreadStackNodeList;
+
+STATIC THREAD_STACK_NODE * ThreadStackNodeInit (Thread *thread)
+{
+ THREAD_STACK_NODE *ThreadStackNodeTmp =
+ AllocateZeroPool (sizeof (THREAD_STACK_NODE));
+
+ if (ThreadStackNodeTmp == NULL) {
+ DEBUG ((EFI_D_ERROR, "Failed to Allocate memory for "
+ "ThreadStackNodeTmp\n"));
+ return NULL;
+ }
+
+ list_clear_node (&ThreadStackNodeTmp->Node);
+
+ ThreadStackNodeTmp->ThreadStackEntry =
+ AllocateZeroPool (sizeof (THREAD_STACK_ENTRY));
+
+ if (!ThreadStackNodeTmp->ThreadStackEntry) {
+ DEBUG ((EFI_D_ERROR, "Failed to Allocate memory for "
+ "ThreadStackNodeTmp->ThreadStackEntry\n"));
+ FreePool (ThreadStackNodeTmp);
+ ThreadStackNodeTmp = NULL;
+ return NULL;
+ }
+
+ ThreadStackNodeTmp->ThreadStackEntry->Thread = thread;
+
+ ThreadStackNodeTmp->ThreadStackEntry->StackBottom =
+ AllocateZeroPool (BOOT_LOADER_MAX_UNSAFE_STACK_SIZE);
+
+ if (!ThreadStackNodeTmp->ThreadStackEntry->StackBottom) {
+ DEBUG ((EFI_D_ERROR, "Failed to Allocate memory for "
+ "ThreadStackNodeTmp->ThreadStackEntry->StackBottom \n"));
+ FreePool (ThreadStackNodeTmp->ThreadStackEntry);
+ FreePool (ThreadStackNodeTmp);
+ ThreadStackNodeTmp->ThreadStackEntry = NULL;
+ ThreadStackNodeTmp = NULL;
+ return NULL;
+ }
+
+ ThreadStackNodeTmp->ThreadStackEntry->StackTop =
+ ThreadStackNodeTmp->ThreadStackEntry->StackBottom;
+ ThreadStackNodeTmp->ThreadStackEntry->StackTop
+ += BOOT_LOADER_MAX_UNSAFE_STACK_SIZE;
+
+ return ThreadStackNodeTmp;
+}
+
+/* If kernel version is bigger than EFI_KERNEL_PROTOCOL_VER_UNSAFE_STACK_APIS,
+ * use API to set/get stack, or else use link table
+**/
+STATIC EFI_STATUS ThreadStackListCreate (VOID)
+{
+ ThreadStackNodeList = AllocateZeroPool (sizeof (THREAD_STACK_NODE));
+ if (!ThreadStackNodeList) {
+ DEBUG ((EFI_D_ERROR, "Failed to Allocate memory for stack list \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ list_initialize (&ThreadStackNodeList->Node);
+ //No entry for head
+ ThreadStackNodeList->ThreadStackEntry = NULL;
+ return EFI_SUCCESS;
+}
+
+STATIC THREAD_STACK_NODE *GetStackTableByThread (Thread *CurrentThread)
+{
+ THREAD_STACK_NODE *ThreadStackNodeTmp = NULL, *ThreadStackNode = NULL;
+
+ if (ThreadStackNodeList == NULL) {
+ DEBUG ((EFI_D_ERROR, "getStackTableByThread ThreadStackNode not"
+ "created\n"));
+ return NULL;
+ }
+
+ if (CurrentThread == NULL) {
+ DEBUG ((EFI_D_ERROR, "getStackTableByThread CurrentThread is NULL \n"));
+ return NULL;
+ }
+
+ list_for_every_entry_safe (&(ThreadStackNodeList->Node), ThreadStackNode,
+ ThreadStackNodeTmp, THREAD_STACK_NODE, Node) {
+ if (ThreadStackNode->ThreadStackEntry &&
+ (ThreadStackNode->ThreadStackEntry->Thread == CurrentThread)) {
+ return ThreadStackNode;
+ }
+ }
+
+ return NULL;
+}
+
+VOID ThreadStackNodeRemove (Thread *CurrentThread)
+{
+ THREAD_STACK_NODE *ThreadStackNodeTmp = NULL;
+
+ if (IsThreadUSSLLSupported) {
+ return;
+ }
+
+ if (CurrentThread == NULL) {
+ DEBUG ((EFI_D_VERBOSE, "Remove NULL thread pointer, drop it\n"));
+ return ;
+ }
+
+ ThreadStackNodeTmp = GetStackTableByThread (CurrentThread);
+ if (!ThreadStackNodeTmp) {
+ DEBUG ((EFI_D_VERBOSE, "try to remove a NULL node"));
+ return ;
+ }
+
+ //Remove and clean current thread stack
+ list_delete (&ThreadStackNodeTmp->Node);
+ FreePool (ThreadStackNodeTmp->ThreadStackEntry->StackBottom);
+ ThreadStackNodeTmp->ThreadStackEntry->StackBottom = NULL;
+ ThreadStackNodeTmp->ThreadStackEntry->StackTop = NULL;
+ ThreadStackNodeTmp->ThreadStackEntry->Thread = NULL;
+ FreePool (ThreadStackNodeTmp->ThreadStackEntry);
+ ThreadStackNodeTmp->ThreadStackEntry = NULL;
+ FreePool (ThreadStackNodeTmp);
+ ThreadStackNodeTmp = NULL;
+
+ DEBUG ((EFI_D_VERBOSE, " remove CurrentThread = %r stack\n", CurrentThread));
+
+ return;
+}
+
+STATIC EFI_STATUS __attribute__ ( (no_sanitize ("safe-stack")))
+AllocateGlobalUnSafeStackPtr (VOID)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ UnSafeStackPtr = AllocateZeroPool (BOOT_LOADER_MAX_UNSAFE_STACK_SIZE);
+ if (UnSafeStackPtr == NULL) {
+ DEBUG ((EFI_D_ERROR, "Failed to Allocate memory for UnSafeStack \n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ return Status;
+ }
+
+ UnSafeStackPtr += BOOT_LOADER_MAX_UNSAFE_STACK_SIZE;
+
+ return Status;
+}
+
+/* Add stack and thread in list, then we can get stack by thread.
+ */
+EFI_STATUS __attribute__ ( (no_sanitize ("safe-stack")))
+AllocateUnSafeStackPtr (Thread *CurrentThread)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ THREAD_STACK_NODE *ThreadStackNodeTmp = NULL;
+ VOID* UnSafeStackPtr = NULL;
+ ThrUnsafeStackIntf ThrUnsafeStackIntf = {
+ NULL,
+ BOOT_LOADER_MAX_UNSAFE_STACK_SIZE,
+ ThreadStackReleaseCb,
+ CurrentThread,
+ };
+
+ if (CurrentThread == NULL) {
+ DEBUG ((EFI_D_ERROR, "Add NULL thread pointer, drop it\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsThreadUSSLLSupported) {
+ UnSafeStackPtr = AllocatePages (ALIGN_PAGES (
+ BOOT_LOADER_MAX_UNSAFE_STACK_SIZE, ALIGNMENT_MASK_4KB));
+ if (UnSafeStackPtr == NULL) {
+ DEBUG ((EFI_D_ERROR, "Failed to Allocate memory for UnSafeStack \n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ return Status;
+ }
+
+ DEBUG ((EFI_D_VERBOSE, "AllocateUnSafeStackPtr CurrentThread = 0x%x,"
+ "UnSafeStackPtr = 0x%x with API \n", CurrentThread, UnSafeStackPtr));
+
+ ThrUnsafeStackIntf.unsafe_sp_base = UnSafeStackPtr;
+
+ Status = KernIntf->Thread->ThreadSetUnsafeSP (CurrentThread,
+ &ThrUnsafeStackIntf);
+
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "AllocateUnSafeStackPtr ThreadSetThreadUnsafeSP"
+ "failed, Status = %d \n", Status));
+ }
+
+ return Status;
+ }
+
+ //Thread unsafe stack low level is not supported, set stack by link table
+ DEBUG ((EFI_D_VERBOSE, "AllocateUnSafeStackPtr CurrentThread = 0x%x with link"
+ "table \n", CurrentThread));
+ if (ThreadStackNodeList == NULL) {
+ DEBUG ((EFI_D_ERROR, "ThreadStackNodeAppend ThreadStackNode not"
+ "created.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ ThreadStackNodeTmp = ThreadStackNodeInit (CurrentThread);
+ if (!ThreadStackNodeTmp) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ list_add_tail (&ThreadStackNodeList->Node, &ThreadStackNodeTmp->Node);
+
+ return EFI_SUCCESS;
+}
+
+//This function is to return the Unsafestack ptr address
+VOID** __attribute__ ( (no_sanitize ("safe-stack")))
+__safestack_pointer_address (VOID)
+{
+ THREAD_STACK_NODE *ThreadStackNodeTmp = NULL;
+
+ if (!IsMultiStack) {
+ return (VOID**) &UnSafeStackPtr;
+ }
+
+ if (KernIntf == NULL) {
+ return NULL;
+ }
+
+ if (IsThreadUSSLLSupported) {
+ return KernIntf->Thread->ThreadGetUnsafeSPCurrent (
+ KernIntf->Thread->GetCurrentThread ());
+ }
+
+ //Thread unsafe stack low level is not supported, get stack by link table
+ ThreadStackNodeTmp =
+ GetStackTableByThread (KernIntf->Thread->GetCurrentThread ());
+ if (!ThreadStackNodeTmp ||
+ !ThreadStackNodeTmp->ThreadStackEntry) {
+ return (VOID**) &UnSafeStackPtr;
+ }
+
+ return (VOID**) &(ThreadStackNodeTmp->ThreadStackEntry->StackTop);
+}
+
+/**
+ If IsThreadUSSLLSupported is true, UEFI core will call back here to free
+ stack, if false, UEFI client link table use ThreadStackNodeRemove () to free
+ stack.
+ **/
+VOID ThreadStackReleaseCb (VOID * Arg)
+{
+ VOID* UnSafeStackPtr = NULL;
+ Thread *CurrentThread = (Thread *)Arg;
+ if (IsThreadUSSLLSupported) {
+ UnSafeStackPtr = KernIntf->Thread->ThreadGetUnsafeSPBase (CurrentThread);
+ DEBUG ((EFI_D_VERBOSE, "ThreadStackReleaseCb UnSafeStackPtr = 0x%x\n",
+ UnSafeStackPtr));
+
+ FreePages (UnSafeStackPtr, ALIGN_PAGES (
+ BOOT_LOADER_MAX_UNSAFE_STACK_SIZE, ALIGNMENT_MASK_4KB));
+
+ UnSafeStackPtr = NULL;
+ }
+}
+
+/* 1. if EFI Kernel Protocol is not supported in UEFI core, allocate global
+ stack for main and timer;
+ 2. If supported, but kernel version is smaller than
+ EFI_KERNEL_PROTOCOL_VER_UNSAFE_STACK_APIS, alloctate by link table;
+ 3. If equal to or bigger, nothing need to to in ABL, UEFI core will manage
+ main and timer thread stack;
+ */
+EFI_STATUS InitThreadUnsafeStack (VOID)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ Status = gBS->LocateProtocol (&gEfiKernelProtocolGuid, NULL,
+ (VOID **)&KernIntf);
+
+ if ((Status != EFI_SUCCESS) ||
+ (KernIntf == NULL) ||
+ KernIntf->Version < EFI_KERNEL_PROTOCOL_VER_THR_CPU_STATS) {
+ DEBUG ((EFI_D_VERBOSE, "multi stack is not supported, using global"
+ " single stack.\n"));
+
+ IsMultiStack = FALSE;
+ return AllocateGlobalUnSafeStackPtr ();
+ }
+
+ DEBUG ((EFI_D_VERBOSE, "SetThreadStackEnv () kernel version = 0x%x \n",
+ KernIntf->Version));
+ if (KernIntf->Version >= EFI_KERNEL_PROTOCOL_VER_UNSAFE_STACK_APIS) {
+ IsThreadUSSLLSupported = TRUE;
+ }
+
+ if (!IsThreadUSSLLSupported) {
+ //Allocate gloabl anyway, if some thread get null stack, return gloabal
+ AllocateGlobalUnSafeStackPtr ();
+
+ Status = ThreadStackListCreate ();
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_VERBOSE, "Unable to Init thread unsafe stack: %r.\n",
+ Status));
+ return Status;
+ }
+
+ Status = AllocateUnSafeStackPtr (KernIntf->Thread->GetCurrentThread ());
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Unable to Allocate memory for Unsafe Stack: %r\n",
+ Status));
+ return Status;
+ }
+ }
+ return Status;
+}
diff --git a/QcomModulePkg/Library/BootLib/UpdateDeviceTree.c b/QcomModulePkg/Library/BootLib/UpdateDeviceTree.c
index cfd6400..80dd9f8 100644
--- a/QcomModulePkg/Library/BootLib/UpdateDeviceTree.c
+++ b/QcomModulePkg/Library/BootLib/UpdateDeviceTree.c
@@ -71,6 +71,24 @@
}
STATIC EFI_STATUS
+ValidateDdrRankChannel (struct ddr_details_entry_info *DdrInfo)
+{
+ if (DdrInfo->num_channels > MAX_CHANNELS) {
+ DEBUG ((EFI_D_ERROR, "ERROR: Number of channels is over the limit\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (UINT8 Chan = 0; Chan < DdrInfo->num_channels; Chan++) {
+ if (DdrInfo->num_ranks[Chan] > MAX_RANKS) {
+ DEBUG ((EFI_D_ERROR, "ERROR: Number of ranks is over the limit\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC EFI_STATUS
GetDDRInfo (struct ddr_details_entry_info *DdrInfo,
UINT64 *Revision)
{
@@ -91,6 +109,7 @@
DEBUG ((EFI_D_ERROR, "INFO: GetDDR details failed\n"));
return Status;
}
+
*Revision = DdrInfoIf->Revision;
DEBUG ((EFI_D_VERBOSE, "DDR Header Revision =0x%x\n", *Revision));
return Status;
@@ -347,15 +366,11 @@
return Status;
}
- Status = GetRamPartitions (&RamPartitions, &NumPartitions);
+ Status = ReadRamPartitions (&RamPartitions, &NumPartitions);
if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Error returned from GetRamPartitions %r\n", Status));
+ DEBUG ((EFI_D_ERROR, "Error returned from ReadRamPartitions %r\n", Status));
return Status;
}
- if (!RamPartitions) {
- DEBUG ((EFI_D_ERROR, "RamPartitions is NULL\n"));
- return EFI_NOT_FOUND;
- }
DEBUG ((EFI_D_INFO, "RAM Partitions\r\n"));
for (i = 0; i < NumPartitions; i++) {
@@ -379,6 +394,7 @@
FreePool (RamPartitions);
RamPartitions = NULL;
+ RamPartitionEntries = NULL;
return EFI_SUCCESS;
}
@@ -550,6 +566,11 @@
"ddr_device_rank, HBB not supported in Revision=0x%x\n",
Revision));
} else {
+ Status = ValidateDdrRankChannel (DdrInfo);
+ if (Status != EFI_SUCCESS) {
+ goto OutofUpdateRankChannel;
+ }
+
DEBUG ((EFI_D_VERBOSE, "DdrInfo->num_channels:%d\n",
DdrInfo->num_channels));
for (UINT8 Chan = 0; Chan < DdrInfo->num_channels; Chan++) {
@@ -590,6 +611,8 @@
}
}
+OutofUpdateRankChannel:
+
UpdateSplashMemInfo (fdt);
/* Get offset of the chosen node */
diff --git a/QcomModulePkg/Library/FastbootLib/FastbootCmds.c b/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
old mode 100644
new mode 100755
index 6849d6d..94d0228
--- a/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
+++ b/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
@@ -56,6 +56,7 @@
#include <Library/PartitionTableUpdate.h>
#include <Library/PcdLib.h>
#include <Library/PrintLib.h>
+#include <Library/ThreadStack.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
@@ -170,7 +171,12 @@
STATIC UINT8 *mFlashDataBuffer = NULL;
STATIC UINT8 *mUsbDataBuffer = NULL;
+STATIC EFI_KERNEL_PROTOCOL *KernIntf = NULL;
+STATIC BOOLEAN IsMultiThreadSupported = FALSE;
STATIC BOOLEAN IsFlashComplete = TRUE;
+STATIC LockHandle *LockDownload;
+STATIC LockHandle *LockFlash;
+
STATIC EFI_STATUS FlashResult = EFI_SUCCESS;
#ifdef ENABLE_UPDATE_PARTITIONS_CMDS
STATIC EFI_EVENT UsbTimerEvent;
@@ -204,13 +210,34 @@
VOID *Data;
} CmdInfo;
+typedef struct {
+ CHAR16 PartitionName[MAX_GPT_NAME_SIZE];
+ UINT32 PartitionSize;
+ UINT8 *FlashDataBuffer;
+ UINT64 FlashNumDataBytes;
+} FlashInfo;
+
+STATIC BOOLEAN FlashSplitNeeded;
STATIC BOOLEAN UsbTimerStarted;
-BOOLEAN IsUsbTimerStarted (VOID)
-{
+BOOLEAN IsUsbTimerStarted (VOID) {
return UsbTimerStarted;
}
+BOOLEAN IsFlashSplitNeeded (VOID)
+{
+ if (IsUseMThreadParallel ()) {
+ return FlashSplitNeeded;
+ } else {
+ return UsbTimerStarted;
+ }
+}
+
+BOOLEAN FlashComplete (VOID)
+{
+ return IsFlashComplete;
+}
+
#ifdef DISABLE_PARALLEL_DOWNLOAD_FLASH
BOOLEAN IsDisableParallelDownloadFlash (VOID)
{
@@ -1290,6 +1317,59 @@
return Status;
}
+
+INT32 __attribute__ ( (no_sanitize ("safe-stack")))
+SparseImgFlashThread (VOID* Arg)
+{
+ Thread* CurrentThread = KernIntf->Thread->GetCurrentThread ();
+ FlashInfo* ThreadFlashInfo = (FlashInfo*) Arg;
+
+ if (!ThreadFlashInfo || !ThreadFlashInfo->FlashDataBuffer) {
+ return 0;
+ }
+
+ KernIntf->Lock->AcquireLock (LockFlash);
+ IsFlashComplete = FALSE;
+ FlashSplitNeeded = TRUE;
+
+ HandleSparseImgFlash (ThreadFlashInfo->PartitionName,
+ ThreadFlashInfo->PartitionSize,
+ ThreadFlashInfo->FlashDataBuffer,
+ ThreadFlashInfo->FlashNumDataBytes);
+
+ FlashSplitNeeded = FALSE;
+ IsFlashComplete = TRUE;
+ KernIntf->Lock->ReleaseLock (LockFlash);
+
+ ThreadStackNodeRemove (CurrentThread);
+
+ FreePool (ThreadFlashInfo);
+ ThreadFlashInfo = NULL;
+
+ KernIntf->Thread->ThreadExit (0);
+
+ return 0;
+}
+
+EFI_STATUS CreateSparseImgFlashThread (IN FlashInfo* ThreadFlashInfo)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ Thread* SparseImgFlashTD = NULL;
+
+ SparseImgFlashTD = KernIntf->Thread->ThreadCreate ("SparseImgFlashThread",
+ SparseImgFlashThread, (VOID*)ThreadFlashInfo, UEFI_THREAD_PRIORITY,
+ DEFAULT_STACK_SIZE);
+
+ if (SparseImgFlashTD == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ AllocateUnSafeStackPtr (SparseImgFlashTD);
+
+ Status = KernIntf->Thread->ThreadResume (SparseImgFlashTD);
+ return Status;
+}
+
#endif
/* Handle Download Command */
@@ -1335,6 +1415,11 @@
gBS->CopyMem (GetFastbootDeviceData ()->gTxBuffer, Response,
sizeof (Response));
+
+ if (IsUseMThreadParallel ()) {
+ KernIntf->Lock->AcquireLock (LockDownload);
+ }
+
mState = ExpectDataState;
mBytesReceivedSoFar = 0;
GetFastbootDeviceData ()->UsbDeviceProtocol->Send (
@@ -1383,6 +1468,7 @@
gBS->CloseEvent (UsbTimerEvent);
UsbTimerEvent = NULL;
}
+
UsbTimerStarted = FALSE;
}
#else
@@ -1508,10 +1594,20 @@
{
VOID *mTmpbuff;
+ if (IsUseMThreadParallel ()) {
+ KernIntf->Lock->AcquireLock (LockDownload);
+ KernIntf->Lock->AcquireLock (LockFlash);
+ }
+
mTmpbuff = mUsbDataBuffer;
mUsbDataBuffer = mFlashDataBuffer;
mFlashDataBuffer = mTmpbuff;
mFlashNumDataBytes = mNumDataBytes;
+
+ if (IsUseMThreadParallel ()) {
+ KernIntf->Lock->ReleaseLock (LockFlash);
+ KernIntf->Lock->ReleaseLock (LockDownload);
+ }
}
STATIC EFI_STATUS
@@ -1754,29 +1850,54 @@
goto out;
}
- IsFlashComplete = FALSE;
PartitionSize = (BlockIo->Media->LastBlock + 1)
* (BlockIo->Media->BlockSize);
if ((PartitionSize > MaxDownLoadSize) &&
!IsDisableParallelDownloadFlash ()) {
- Status = HandleUsbEventsInTimer ();
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Failed to handle usb event: %r\n", Status));
- IsFlashComplete = TRUE;
- StopUsbTimer ();
+ if (IsUseMThreadParallel ()) {
+ FlashInfo* ThreadFlashInfo = AllocateZeroPool (sizeof (FlashInfo));
+ if (!ThreadFlashInfo) {
+ DEBUG ((EFI_D_ERROR,
+ "ERROR: Failed to allocate memory for ThreadFlashInfo\n"));
+ return ;
+ }
+
+ ThreadFlashInfo->FlashDataBuffer = mFlashDataBuffer,
+ ThreadFlashInfo->FlashNumDataBytes = mFlashNumDataBytes;
+
+ StrnCpyS (ThreadFlashInfo->PartitionName, MAX_GPT_NAME_SIZE,
+ PartitionName, ARRAY_SIZE (PartitionName));
+ ThreadFlashInfo->PartitionSize = ARRAY_SIZE (PartitionName);
+
+ Status = CreateSparseImgFlashThread (ThreadFlashInfo);
} else {
- UsbTimerStarted = TRUE;
+ IsFlashComplete = FALSE;
+
+ Status = HandleUsbEventsInTimer ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Failed to handle usb event: %r\n", Status));
+ IsFlashComplete = TRUE;
+ StopUsbTimer ();
+ } else {
+ UsbTimerStarted = TRUE;
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
FastbootOkay ("");
}
}
- FlashResult = HandleSparseImgFlash (PartitionName,
+ if (EFI_ERROR (Status) ||
+ !IsUseMThreadParallel () ||
+ (PartitionSize <= MaxDownLoadSize)) {
+ FlashResult = HandleSparseImgFlash (PartitionName,
ARRAY_SIZE (PartitionName),
mFlashDataBuffer, mFlashNumDataBytes);
-
- IsFlashComplete = TRUE;
- StopUsbTimer ();
+ IsFlashComplete = TRUE;
+ StopUsbTimer ();
+ }
} else if (!AsciiStrnCmp (UbiHeader->HdrMagic, UBI_HEADER_MAGIC, 4)) {
FlashResult = HandleUbiImgFlash (PartitionName,
ARRAY_SIZE (PartitionName),
@@ -1851,6 +1972,8 @@
CHAR8 EraseResultStr[MAX_RSP_SIZE] = "";
VirtualAbMergeStatus SnapshotMergeStatus;
+ WaitForFlashFinished ();
+
if (AsciiStrLen (arg) >= MAX_GPT_NAME_SIZE) {
FastbootFail ("Invalid partition name");
return;
@@ -2123,11 +2246,17 @@
gBS->SetMem ((VOID *)(Data + mNumDataBytes), RoundSize - mNumDataBytes,
0);
}
- /* Stop usb timer after data transfer completed */
- StopUsbTimer ();
- /* Postpone Fastboot Okay until flash completed */
- FastbootOkayDelay ();
mState = ExpectCmdState;
+
+ if (IsUseMThreadParallel ()) {
+ KernIntf->Lock->ReleaseLock (LockDownload);
+ FastbootOkay ("");
+ } else {
+ /* Stop usb timer after data transfer completed */
+ StopUsbTimer ();
+ /* Postpone Fastboot Okay until flash completed */
+ FastbootOkayDelay ();
+ }
} else {
GetFastbootDeviceData ()->UsbDeviceProtocol->Send (
ENDPOINT_IN, GetXfrSize (), (Data + mBytesReceivedSoFar));
@@ -2266,6 +2395,68 @@
return;
}
+//Shoud block command until flash finished
+VOID WaitForFlashFinished (VOID)
+{
+ if (!IsFlashComplete &&
+ IsUseMThreadParallel ()) {
+ KernIntf->Lock->AcquireLock (LockFlash);
+ KernIntf->Lock->ReleaseLock (LockFlash);
+ }
+}
+
+VOID ThreadSleep (TimeDuration Delay)
+{
+ KernIntf->Thread->ThreadSleep (Delay);
+}
+
+BOOLEAN IsUseMThreadParallel (VOID)
+{
+ if (FixedPcdGetBool (EnableMultiThreadFlash)) {
+ return IsMultiThreadSupported;
+ }
+
+ return FALSE;
+}
+
+VOID InitMultiThreadEnv ()
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (IsDisableParallelDownloadFlash ()) {
+ return;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiKernelProtocolGuid, NULL,
+ (VOID **)&KernIntf);
+
+ if ((Status != EFI_SUCCESS) ||
+ (KernIntf == NULL) ||
+ KernIntf->Version < EFI_KERNEL_PROTOCOL_VER_UNSAFE_STACK_APIS) {
+ DEBUG ((EFI_D_VERBOSE, "Multi thread is not supported.\n"));
+ return;
+ }
+
+ KernIntf->Lock->InitLock ("DOWNLOAD", &LockDownload);
+ if (&LockDownload == NULL) {
+ DEBUG ((EFI_D_ERROR, "InitLock LockDownload error \n"));
+ return;
+ }
+
+ KernIntf->Lock->InitLock ("FLASH", &LockFlash);
+ if (&LockFlash == NULL) {
+ DEBUG ((EFI_D_ERROR, "InitLock LockFlash error \n"));
+ KernIntf->Lock->DestroyLock (LockDownload);
+ return;
+ }
+
+ //init MultiThreadEnv succeeded, use multi thread to flash
+ IsMultiThreadSupported = TRUE;
+
+ DEBUG ((EFI_D_VERBOSE,
+ "InitMultiThreadEnv successfully, will use thread to flash \n"));
+}
+
EFI_STATUS
FastbootCmdsInit (VOID)
{
@@ -2338,6 +2529,9 @@
MaxDownLoadSize : MaxDownLoadSize / 2;
FastbootCommandSetup ((VOID *)FastBootBuffer, MaxDownLoadSize);
+
+ InitMultiThreadEnv ();
+
return EFI_SUCCESS;
}
@@ -3116,7 +3310,8 @@
/* Wait for flash finished before next command */
if (AsciiStrnCmp (Data, "download", AsciiStrLen ("download"))) {
StopUsbTimer ();
- if (!IsFlashComplete) {
+ if (!IsFlashComplete &&
+ !IsUseMThreadParallel ()) {
Status = AcceptCmdTimerInit (Size, Data);
if (Status == EFI_SUCCESS) {
return;
diff --git a/QcomModulePkg/Library/FastbootLib/FastbootCmds.h b/QcomModulePkg/Library/FastbootLib/FastbootCmds.h
old mode 100644
new mode 100755
index 57ec9a5..7fb91c1
--- a/QcomModulePkg/Library/FastbootLib/FastbootCmds.h
+++ b/QcomModulePkg/Library/FastbootLib/FastbootCmds.h
@@ -2,7 +2,7 @@
* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -38,6 +38,7 @@
#include <Library/LinuxLoaderLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PartitionTableUpdate.h>
+#include <Protocol/EFIKernelInterface.h>
#define ENDPOINT_IN 0x01
#define ENDPOINT_OUT 0x81
@@ -173,5 +174,10 @@
UpdateDevInfo (CHAR16 *Pname, CHAR8 *ImgVersion);
VOID
GetDevInfo (DeviceInfo **DevinfoPtr);
-BOOLEAN IsUsbTimerStarted (VOID);
+BOOLEAN IsFlashSplitNeeded (VOID);
+BOOLEAN FlashComplete (VOID);
+BOOLEAN IsDisableParallelDownloadFlash (VOID);
+BOOLEAN IsUseMThreadParallel (VOID);
+VOID ThreadSleep (TimeDuration Delay);
+VOID WaitForFlashFinished (VOID);
#endif
diff --git a/QcomModulePkg/Library/FastbootLib/FastbootLib.inf b/QcomModulePkg/Library/FastbootLib/FastbootLib.inf
index b371aa1..54698ea 100644
--- a/QcomModulePkg/Library/FastbootLib/FastbootLib.inf
+++ b/QcomModulePkg/Library/FastbootLib/FastbootLib.inf
@@ -1,5 +1,5 @@
#/*
-# * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+# * Copyright (c) 2015-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
@@ -99,3 +99,4 @@
[FixedPcd]
gQcomTokenSpaceGuid.EnableMdtpSupport
gQcomTokenSpaceGuid.EnableBatteryVoltageCheck
+ gQcomTokenSpaceGuid.EnableMultiThreadFlash
diff --git a/QcomModulePkg/Library/FastbootLib/FastbootMain.c b/QcomModulePkg/Library/FastbootLib/FastbootMain.c
index 4ba5354..ae01672 100755
--- a/QcomModulePkg/Library/FastbootLib/FastbootMain.c
+++ b/QcomModulePkg/Library/FastbootLib/FastbootMain.c
@@ -14,7 +14,7 @@
**/
-/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
diff --git a/QcomModulePkg/Library/avb/VerifiedBoot.c b/QcomModulePkg/Library/avb/VerifiedBoot.c
old mode 100644
new mode 100755
index 0d3540c..d276294
--- a/QcomModulePkg/Library/avb/VerifiedBoot.c
+++ b/QcomModulePkg/Library/avb/VerifiedBoot.c
@@ -31,6 +31,7 @@
#include "BootImage.h"
#include "KeymasterClient.h"
#include "libavb/libavb.h"
+#include <FastbootLib/FastbootCmds.h>
#include <Library/MenuKeysDetection.h>
#include <Library/VerifiedBootMenu.h>
#include <Library/LEOEMCertificate.h>
@@ -1133,6 +1134,8 @@
IsDynamicPartitionSupport ()) &&
(Info->BootIntoRecovery &&
!IsBuildUseRecoveryAsBoot ())) {
+ if (!Info->MultiSlotBoot)
+ VerifyFlags = VerifyFlags | AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION;
AddRequestedPartition (RequestedPartitionAll, IMG_RECOVERY);
NumRequestedPartition += 1;
Result = avb_slot_verify (Ops, (CONST CHAR8 *CONST *)RequestedPartition,
@@ -1579,6 +1582,8 @@
QCOM_MDTP_PROTOCOL *MdtpProtocol;
UINT32 AVBVersion = NO_AVB;
+ WaitForFlashFinished ();
+
if (Info == NULL) {
DEBUG ((EFI_D_ERROR, "Invalid parameter Info\n"));
return EFI_INVALID_PARAMETER;
diff --git a/QcomModulePkg/Library/avb/libavb/avb_ops.c b/QcomModulePkg/Library/avb/libavb/avb_ops.c
index 0afd22b..1fe1258 100644
--- a/QcomModulePkg/Library/avb/libavb/avb_ops.c
+++ b/QcomModulePkg/Library/avb/libavb/avb_ops.c
@@ -117,14 +117,6 @@
EFI_GUID *Guid;
}AvbPartitionDetails;
-static AvbPartitionDetails SupportedPartitions[] =
-{
- { "vbmeta", &gEfiVbmetaPartitionGuid },
- { "boot", &gEfiBootImgPartitionGuid },
- { "dtbo", &gEfiDtboPartitionGuid },
- { "recovery", &gEfiRecoveryImgPartitionGuid} ,
-};
-
AvbIOResult AvbReadFromPartition(AvbOps *Ops, const char *Partition, int64_t ReadOffset,
size_t NumBytes, void *Buffer, size_t *OutNumRead)
{
@@ -140,12 +132,6 @@
UINT64 LastBlock = 0;
UINT64 FullBlock = 0;
UINT64 StartPageReadSize = 0;
- UINT32 BlkIOAttrib = 0;
- PartiSelectFilter HandleFilter;
- UINT32 MaxHandles = 0;
- AvbPartitionDetails *List = SupportedPartitions;
- UINT32 Count = ARRAY_SIZE (SupportedPartitions);
- EFI_GUID *PType = NULL;
UINT64 LoadImageStartTime = GetTimerCountms ();
if (Partition == NULL || Buffer == NULL || OutNumRead == NULL || NumBytes <= 0) {
@@ -155,57 +141,13 @@
}
*OutNumRead = 0;
- for (size_t Index = 0; Index < Count; Index++) {
- if (!AsciiStrCmp (List[Index].Name, Partition)) {
- DEBUG ((EFI_D_INFO,
- "Partition found: %a\n", Partition));
- PType = List[Index].Guid;
- }
+ Result = GetHandleInfo (Partition, InfoList);
+ if (Result != AVB_IO_RESULT_OK) {
+ DEBUG ((EFI_D_ERROR,
+ "AvbGetSizeOfPartition: GetHandleInfo failed"));
+ goto out;
}
- if (PType) {
- BlkIOAttrib = BLK_IO_SEL_PARTITIONED_GPT;
- BlkIOAttrib |= BLK_IO_SEL_MEDIA_TYPE_NON_REMOVABLE;
- BlkIOAttrib |= BLK_IO_SEL_MATCH_PARTITION_TYPE_GUID;
-
- HandleFilter.RootDeviceType = NULL;
- HandleFilter.PartitionType = PType;
- HandleFilter.VolumeName = NULL;
-
- MaxHandles = ARRAY_SIZE (InfoList);
-
- Status = GetBlkIOHandles (BlkIOAttrib, &HandleFilter,
- InfoList, &MaxHandles);
- if (Status == EFI_SUCCESS) {
- if (MaxHandles == 0) {
- DEBUG ((EFI_D_INFO,
- "Partition Not found: %s\n", Partition));
- Result = AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
- goto out;
- }
-
- if (MaxHandles != 1) {
- /* Unable to deterministically load from single partition */
- DEBUG ((EFI_D_INFO,
- "multiple partitions found: %s\n", Partition));
- Result = AVB_IO_RESULT_ERROR_IO;
- goto out;
- }
- } else {
- DEBUG ((EFI_D_INFO,
- "GetBlkIOHandles failed with error: %d\n", Status));
- Result = AVB_IO_RESULT_ERROR_IO;
- goto out;
- }
- } else {
- Result = GetHandleInfo (Partition, InfoList);
- if (Result != AVB_IO_RESULT_OK) {
- DEBUG ((EFI_D_ERROR,
- "AvbGetSizeOfPartition: GetHandleInfo failed"));
- goto out;
- }
- }
-
BlockIo = InfoList[0].BlkIo;
PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize;
@@ -428,6 +370,34 @@
return AVB_IO_RESULT_OK;
}
+
+AvbIOResult
+AvbValidatePartitionPublicKey(AvbOps *Ops, const char* Partition,
+ const uint8_t *PublicKeyData, size_t PublicKeyLength,
+ const uint8_t *PublicKeyMetadata, size_t PublicKeyMetadataLength,
+ bool *OutIsTrusted, uint32_t* OutRollbackIndexLocation)
+{
+ DEBUG((EFI_D_VERBOSE, "ValidatePartitionPublicKey PublicKeyLength %d, "
+ "PublicKeyMetadataLength %d\n",
+ PublicKeyLength, PublicKeyMetadataLength));
+
+ if (OutIsTrusted == NULL || PublicKeyData == NULL) {
+ DEBUG((EFI_D_ERROR, "Invalid parameters\n"));
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+
+ if (PublicKeyLength == ARRAY_SIZE(OEMPublicKey) &&
+ CompareMem(PublicKeyData, OEMPublicKey, PublicKeyLength) == 0) {
+ *OutIsTrusted = true;
+ } else {
+ *OutIsTrusted = false;
+ }
+ *OutRollbackIndexLocation = 1; // Recovery rollback index
+ DEBUG((EFI_D_ERROR,
+ "ValidateVbmetaPublicKey OutIsTrusted %d\n",*OutIsTrusted));
+ return AVB_IO_RESULT_OK;
+}
+
AvbIOResult AvbReadRollbackIndex(AvbOps *Ops, size_t RollbackIndexLocation,
uint64_t *OutRollbackIndex)
{
@@ -603,6 +573,7 @@
Ops->read_from_partition = AvbReadFromPartition;
Ops->write_to_partition = AvbWriteToPartition;
Ops->validate_vbmeta_public_key = AvbValidateVbmetaPublicKey;
+ Ops->validate_public_key_for_partition = AvbValidatePartitionPublicKey;
Ops->read_rollback_index = AvbReadRollbackIndex;
Ops->write_rollback_index = AvbWriteRollbackIndex;
Ops->read_is_device_unlocked = AvbReadIsDeviceUnlocked;
diff --git a/QcomModulePkg/Library/avb/libavb/avb_ops.h b/QcomModulePkg/Library/avb/libavb/avb_ops.h
index 8162194..76cc9d4 100644
--- a/QcomModulePkg/Library/avb/libavb/avb_ops.h
+++ b/QcomModulePkg/Library/avb/libavb/avb_ops.h
@@ -155,6 +155,10 @@
*
* If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set -
* true if trusted or false if untrusted.
+ *
+ * NOTE: If AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is passed to
+ * avb_slot_verify() then this operation is never used. Instead, the
+ * validate_public_key_for_partition() operation is used
*/
AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops,
const uint8_t* public_key_data,
@@ -223,6 +227,26 @@
AvbIOResult (*get_size_of_partition)(AvbOps* ops,
const char* partition,
uint64_t* out_size_num_bytes);
+
+ /* Like validate_vbmeta_public_key() but for when the flag
+ * AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is being used. The name of the
+ * partition to get the public key for is passed in |partition_name|.
+ *
+ * Also returns the rollback index location to use for the partition, in
+ * |out_rollback_index_location|.
+ *
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+ */
+ AvbIOResult (*validate_public_key_for_partition)(
+ AvbOps* ops,
+ const char* partition,
+ const uint8_t* public_key_data,
+ size_t public_key_length,
+ const uint8_t* public_key_metadata,
+ size_t public_key_metadata_length,
+ bool* out_is_trusted,
+ uint32_t* out_rollback_index_location);
+
};
typedef struct {
diff --git a/QcomModulePkg/Library/avb/libavb/avb_slot_verify.c b/QcomModulePkg/Library/avb/libavb/avb_slot_verify.c
index fb6fc79..180e2d4 100644
--- a/QcomModulePkg/Library/avb/libavb/avb_slot_verify.c
+++ b/QcomModulePkg/Library/avb/libavb/avb_slot_verify.c
@@ -359,6 +359,7 @@
AvbOps* ops,
const char* const* requested_partitions,
const char* ab_suffix,
+ AvbSlotVerifyFlags flags,
bool allow_verification_error,
AvbVBMetaImageFlags toplevel_vbmeta_flags,
int rollback_index_location,
@@ -398,7 +399,12 @@
* rollback_index_location to determine whether we're the main
* vbmeta struct.
*/
- is_main_vbmeta = (rollback_index_location == 0);
+ is_main_vbmeta = false;
+ if (rollback_index_location == 0) {
+ if ((flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) == 0) {
+ is_main_vbmeta = true;
+ }
+ }
/* Don't use footers for vbmeta partitions ('vbmeta' or
* 'vbmeta_<partition_name>').
@@ -509,6 +515,7 @@
ret = load_and_verify_vbmeta(ops,
requested_partitions,
ab_suffix,
+ flags,
allow_verification_error,
0 /* toplevel_vbmeta_flags */,
0 /* rollback_index_location */,
@@ -585,6 +592,8 @@
}
}
+ uint32_t rollback_index_location_to_use = rollback_index_location;
+
/* Check if key used to make signature matches what is expected. */
if (pk_data != NULL) {
if (expected_public_key != NULL) {
@@ -612,9 +621,27 @@
pk_metadata_len = vbmeta_header.public_key_metadata_size;
}
- avb_assert(is_main_vbmeta);
- io_ret = ops->validate_vbmeta_public_key(
- ops, pk_data, pk_len, pk_metadata, pk_metadata_len, &key_is_trusted);
+ // If we're not using a vbmeta partition, need to use another AvbOps...
+ if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
+ io_ret = ops->validate_public_key_for_partition(
+ ops,
+ full_partition_name,
+ pk_data,
+ pk_len,
+ pk_metadata,
+ pk_metadata_len,
+ &key_is_trusted,
+ &rollback_index_location_to_use);
+ } else {
+ avb_assert(is_main_vbmeta);
+ io_ret = ops->validate_vbmeta_public_key(ops,
+ pk_data,
+ pk_len,
+ pk_metadata,
+ pk_metadata_len,
+ &key_is_trusted);
+ }
+
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
@@ -639,7 +666,7 @@
/* Check rollback index. */
io_ret = ops->read_rollback_index(
- ops, rollback_index_location, &stored_rollback_index);
+ ops, rollback_index_location_to_use, &stored_rollback_index);
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
@@ -679,7 +706,9 @@
if (is_main_vbmeta) {
avb_assert(slot_data->num_vbmeta_images == 0);
} else {
- avb_assert(slot_data->num_vbmeta_images > 0);
+ if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
+ avb_assert(slot_data->num_vbmeta_images > 0);
+ }
}
if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
@@ -804,6 +833,7 @@
sub_ret = load_and_verify_vbmeta(ops,
requested_partitions,
ab_suffix,
+ flags,
allow_verification_error,
toplevel_vbmeta_flags,
chain_desc.rollback_index_location,
@@ -1003,6 +1033,16 @@
}
}
+ /* It's possible there is no _PARTUUID for replacement above.
+ * Duplicate cmdline to ret for additional substitutions below.
+ */
+ if (ret == NULL) {
+ ret = avb_strdup(cmdline);
+ if (ret == NULL) {
+ goto fail;
+ }
+ }
+
return ret;
fail:
@@ -1127,6 +1167,7 @@
static AvbSlotVerifyResult append_options(
AvbOps* ops,
+ AvbSlotVerifyFlags flags,
AvbSlotVerifyData* slot_data,
AvbVBMetaImageHeader* toplevel_vbmeta,
AvbAlgorithmType algorithm_type,
@@ -1144,6 +1185,18 @@
goto out;
}
+ /* Add androidboot.vbmeta.device option... except if not using a vbmeta
+ * partition since it doesn't make sense in that case.
+ */
+ if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
+ if (!cmdline_append_option(slot_data,
+ "androidboot.vbmeta.device",
+ "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ }
+
/* Add androidboot.vbmeta.avb_version option. */
if (!cmdline_append_version(slot_data,
"androidboot.vbmeta.avb_version",
@@ -1334,10 +1387,9 @@
avb_assert(ops->read_is_device_unlocked != NULL);
avb_assert(ops->read_from_partition != NULL);
avb_assert(ops->get_size_of_partition != NULL);
- avb_assert(ops->validate_vbmeta_public_key != NULL);
avb_assert(ops->read_rollback_index != NULL);
avb_assert(ops->get_unique_guid_for_partition != NULL);
- /* avb_assert(ops->get_size_of_partition != NULL); */
+ avb_assert(ops->validate_public_key_for_partition != NULL);
if (out_data != NULL) {
*out_data = NULL;
@@ -1353,6 +1405,21 @@
goto fail;
}
+ /* Make sure passed-in AvbOps support verifying public keys and getting
+ * rollback index location if not using a vbmeta partition.
+ */
+ if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
+ if (ops->validate_public_key_for_partition == NULL) {
+ avb_error(
+ "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION was passed but the "
+ "validate_public_key_for_partition() operation isn't implemented.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto fail;
+ }
+ } else {
+ avb_assert(ops->validate_vbmeta_public_key != NULL);
+ }
+
slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
if (slot_data == NULL) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
@@ -1371,30 +1438,67 @@
goto fail;
}
- ret = load_and_verify_vbmeta(ops,
- requested_partitions,
- ab_suffix,
- allow_verification_error,
- 0 /* toplevel_vbmeta_flags */,
- 0 /* rollback_index_location */,
- "vbmeta",
- avb_strlen("vbmeta"),
- NULL /* expected_public_key */,
- 0 /* expected_public_key_length */,
- slot_data,
- &algorithm_type);
- if ((!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) ||
- !result_should_continue(ret)) {
+ if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
+ if (requested_partitions == NULL || requested_partitions[0] == NULL) {
+ avb_fatal(
+ "Requested partitions cannot be empty when using "
+ "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto fail;
+ }
+
+ /* No vbmeta partition, go through each of the requested partitions... */
+ for (size_t n = 0; requested_partitions[n] != NULL; n++) {
+ ret = load_and_verify_vbmeta(ops,
+ requested_partitions,
+ ab_suffix,
+ flags,
+ allow_verification_error,
+ 0 /* toplevel_vbmeta_flags */,
+ 0 /* rollback_index_location */,
+ requested_partitions[n],
+ avb_strlen(requested_partitions[n]),
+ NULL /* expected_public_key */,
+ 0 /* expected_public_key_length */,
+ slot_data,
+ &algorithm_type);
+ if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto fail;
+ }
+ }
+
+ } else {
+ /* Usual path, load "vbmeta"... */
+ ret = load_and_verify_vbmeta(ops,
+ requested_partitions,
+ ab_suffix,
+ flags,
+ allow_verification_error,
+ 0 /* toplevel_vbmeta_flags */,
+ 0 /* rollback_index_location */,
+ "vbmeta",
+ avb_strlen("vbmeta"),
+ NULL /* expected_public_key */,
+ 0 /* expected_public_key_length */,
+ slot_data,
+ &algorithm_type);
+ if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto fail;
+ }
+ }
+
+ if (!result_should_continue(ret)) {
goto fail;
}
/* If things check out, mangle the kernel command-line as needed. */
- if (result_should_continue(ret)) {
+ if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
avb_assert(
avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
using_boot_for_vbmeta = true;
}
+ }
/* Byteswap top-level vbmeta header since we'll need it below. */
avb_vbmeta_image_header_to_host_byte_order(
@@ -1437,6 +1541,7 @@
* I/O or OOM error.
*/
AvbSlotVerifyResult sub_ret = append_options(ops,
+ flags,
slot_data,
&toplevel_vbmeta,
algorithm_type,
@@ -1464,7 +1569,6 @@
} else {
avb_slot_verify_data_free(slot_data);
}
- }
if (!allow_verification_error) {
avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
diff --git a/QcomModulePkg/Library/avb/libavb/avb_slot_verify.h b/QcomModulePkg/Library/avb/libavb/avb_slot_verify.h
index 2d460fc..9485e8e 100644
--- a/QcomModulePkg/Library/avb/libavb/avb_slot_verify.h
+++ b/QcomModulePkg/Library/avb/libavb/avb_slot_verify.h
@@ -99,10 +99,21 @@
* contents loaded from |requested_partition| will be the contents of
* the entire partition instead of just the size specified in the hash
* descriptor.
+ *
+ * If the AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION flag is set then
+ * data won't be loaded from the "vbmeta" partition and the
+ * |validate_vbmeta_public_key| operation is never called. Instead, the
+ * vbmeta structs in |requested_partitions| are loaded and processed and the
+ * |validate_public_key_for_partition| operation is called for each of these
+ * vbmeta structs. This flag is useful when booting into recovery on a device
+ * not using A/B - see section "Booting into recovery" in README.md for
+ * more information.
*/
typedef enum {
AVB_SLOT_VERIFY_FLAGS_NONE = 0,
- AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0)
+ AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0),
+ AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION = (1 << 1),
+ AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION = (1 << 2),
} AvbSlotVerifyFlags;
/* Get a textual representation of |result|. */
@@ -215,7 +226,9 @@
* PARTUUID=$(ANDROID_VBMETA_PARTUUID) before substitution so it
* will end up pointing to the vbmeta partition for the verified
* slot. If there is no vbmeta partition it will point to the boot
- * partition of the verified slot.
+ * partition of the verified slot. If the flag
+ * AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is used, this is not
+ * set.
*
* androidboot.vbmeta.avb_version: This is set to the decimal value
* of AVB_VERSION_MAJOR followed by a dot followed by the decimal
diff --git a/QcomModulePkg/QcomModulePkg.dec b/QcomModulePkg/QcomModulePkg.dec
index c3baa60..51d6490 100644
--- a/QcomModulePkg/QcomModulePkg.dec
+++ b/QcomModulePkg/QcomModulePkg.dec
@@ -142,6 +142,8 @@
gEfiDDRGetInfoProtocolGuid = { 0x1a7c0eb8, 0x5646, 0x45f7, { 0xab, 0x20, 0xea, 0xe5, 0xda, 0x46, 0x40, 0xa2 } }
# Display Utils Protocol
gQcomDisplayUtilsProtocolGuid = { 0xc0dd69ac, 0x76ba, 0x11e6, { 0xab, 0x24, 0x1f, 0xc7, 0xf5, 0x57, 0x5f, 0x19 } }
+ # Multithreading Kernel protocol for UEFI
+ gEfiKernelProtocolGuid = { 0xB5062BE7, 0x170B, 0x4A32, { 0xBE, 0x21, 0x68, 0x92, 0x62, 0xFF, 0x43, 0x99 } }
[PcdsFixedAtBuild.common]
# LinuxLoaderCommon
@@ -157,3 +159,4 @@
gQcomTokenSpaceGuid.EnableBatteryVoltageCheck|TRUE|BOOLEAN|0x00015009
gQcomTokenSpaceGuid.RamdiskEndAddress32|0x03C00000|UINT32|0x0001500A
gQcomTokenSpaceGuid.EnableNewNodeSearchFuc|TRUE|BOOLEAN|0x0001500B
+ gQcomTokenSpaceGuid.EnableMultiThreadFlash|TRUE|BOOLEAN|0x0001500C