blob: fd5a8372f82fef7b20e1490319ee4ec934ecdbcb [file] [log] [blame]
Channagoud Kadabif8aa7632015-11-12 14:27:01 -08001/*
Bhanuprakash Modem937fc4a2018-06-12 16:11:26 +05302 * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
Channagoud Kadabif8aa7632015-11-12 14:27:01 -08003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * * Neither the name of The Linux Foundation nor
12 * the names of its contributors may be used to endorse or promote
13 * products derived from this software without specific prior written
14 * permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29#include "PartitionTableUpdate.h"
lijuangf0bbcad2017-08-16 16:59:18 +080030#include "AutoGen.h"
Jeevan Shriram17f173d2017-10-24 22:11:07 -070031#include <Library/Board.h>
32#include <Library/BootLinux.h>
33#include <Library/LinuxLoaderLib.h>
34#include <Library/UefiLib.h>
lijuang5b762962019-03-15 20:40:45 +080035#include <Library/DebugLib.h>
Jeevan Shriram17f173d2017-10-24 22:11:07 -070036#include <Uefi.h>
37#include <Uefi/UefiSpec.h>
38#include <VerifiedBoot.h>
lijuangf0bbcad2017-08-16 16:59:18 +080039
Channagoud Kadabi8ad76a72016-02-16 17:26:59 -080040STATIC BOOLEAN FlashingGpt;
41STATIC BOOLEAN ParseSecondaryGpt;
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +053042struct StoragePartInfo Ptable[MAX_LUNS];
43struct PartitionEntry PtnEntries[MAX_NUM_PARTITIONS];
44STATIC UINT32 MaxLuns;
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +053045STATIC UINT32 PartitionCount;
Shivaprasad Hongal340f6872017-04-26 16:15:27 -070046STATIC BOOLEAN FirstBoot;
lijuang5b762962019-03-15 20:40:45 +080047STATIC struct PartitionEntry PtnEntriesBak[MAX_NUM_PARTITIONS];
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +053048
Vijay Kumar Pendotia7e72a02016-11-11 15:36:56 +053049STATIC struct BootPartsLinkedList *HeadNode;
Jeevan Shriram17f173d2017-10-24 22:11:07 -070050STATIC EFI_STATUS
51GetActiveSlot (Slot *ActiveSlot);
Vijay Kumar Pendotia7e72a02016-11-11 15:36:56 +053052
Jeevan Shriram17f173d2017-10-24 22:11:07 -070053Slot GetCurrentSlotSuffix (VOID)
Shivaprasad Hongalc017e812017-04-26 16:15:27 -070054{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070055 Slot CurrentSlot = {{0}};
56 BOOLEAN IsMultiSlot = PartitionHasMultiSlot ((CONST CHAR16 *)L"boot");
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +053057
Jeevan Shriram17f173d2017-10-24 22:11:07 -070058 if (IsMultiSlot == FALSE) {
59 return CurrentSlot;
60 }
lijuanga4c1b082016-12-08 19:12:48 +080061
Jeevan Shriram17f173d2017-10-24 22:11:07 -070062 GetActiveSlot (&CurrentSlot);
63 return CurrentSlot;
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +053064}
65
Jeevan Shriram17f173d2017-10-24 22:11:07 -070066UINT32 GetMaxLuns (VOID)
Jeevan Shriramab436682016-09-23 07:08:06 -070067{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070068 return MaxLuns;
Jeevan Shriramab436682016-09-23 07:08:06 -070069}
70
Jeevan Shriram17f173d2017-10-24 22:11:07 -070071UINT32
72GetPartitionLunFromIndex (UINT32 Index)
Jeevan Shriramab436682016-09-23 07:08:06 -070073{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070074 return PtnEntries[Index].lun;
Jeevan Shriramab436682016-09-23 07:08:06 -070075}
76
Jeevan Shriram17f173d2017-10-24 22:11:07 -070077VOID
78GetPartitionCount (UINT32 *Val)
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +053079{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070080 *Val = PartitionCount;
81 return;
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +053082}
83
Jeevan Shriram17f173d2017-10-24 22:11:07 -070084INT32
85GetPartitionIdxInLun (CHAR16 *Pname, UINT32 Lun)
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +053086{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070087 UINT32 n;
88 UINT32 RelativeIndex = 0;
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +053089
Jeevan Shriram17f173d2017-10-24 22:11:07 -070090 for (n = 0; n < PartitionCount; n++) {
91 if (Lun == PtnEntries[n].lun) {
92 if (!StrnCmp (Pname, PtnEntries[n].PartEntry.PartitionName,
93 ARRAY_SIZE (PtnEntries[n].PartEntry.PartitionName))) {
94 return RelativeIndex;
95 }
96 RelativeIndex++;
lijuang46df8442017-09-28 19:06:36 +080097 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -070098 }
99 return INVALID_PTN;
100}
101
102VOID UpdatePartitionEntries (VOID)
103{
104 UINT32 i;
105 UINT32 j;
106 UINT32 Index = 0;
107 EFI_STATUS Status;
108 EFI_PARTITION_ENTRY *PartEntry;
109
110 PartitionCount = 0;
111 /*Nullify the PtnEntries array before using it*/
112 gBS->SetMem ((VOID *)PtnEntries,
113 (sizeof (PtnEntries[0]) * MAX_NUM_PARTITIONS), 0);
114
115 for (i = 0; i < MaxLuns; i++) {
116 for (j = 0; (j < Ptable[i].MaxHandles) && (Index < MAX_NUM_PARTITIONS);
117 j++, Index++) {
118 Status =
119 gBS->HandleProtocol (Ptable[i].HandleInfoList[j].Handle,
120 &gEfiPartitionRecordGuid, (VOID **)&PartEntry);
121 PartitionCount++;
122 if (EFI_ERROR (Status)) {
123 DEBUG ((EFI_D_VERBOSE, "Selected Lun : %d, handle: %d does not have "
124 "partition record, ignore\n",
125 i, j));
126 PtnEntries[Index].lun = i;
127 continue;
128 }
129
130 gBS->CopyMem ((&PtnEntries[Index]), PartEntry, sizeof (PartEntry[0]));
131 PtnEntries[Index].lun = i;
132 }
133 }
Nagireddy Annem672b53f2019-11-11 13:55:48 +0530134 if (NAND == CheckRootDeviceType ()) {
135 NandABUpdatePartition (PTN_ENTRIES_FROM_MISC);
136 }
lijuang5b762962019-03-15 20:40:45 +0800137 /* Back up the ptn entries */
138 gBS->CopyMem (PtnEntriesBak, PtnEntries, sizeof (PtnEntries));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700139}
140
141INT32
142GetPartitionIndex (CHAR16 *Pname)
143{
144 INT32 i;
145
146 for (i = 0; i < PartitionCount; i++) {
147 if (!StrnCmp (PtnEntries[i].PartEntry.PartitionName, Pname,
148 ARRAY_SIZE (PtnEntries[i].PartEntry.PartitionName))) {
149 return i;
150 }
151 }
152
153 return INVALID_PTN;
154}
155
156STATIC EFI_STATUS
157GetStorageHandle (INT32 Lun, HandleInfo *BlockIoHandle, UINT32 *MaxHandles)
158{
159 EFI_STATUS Status = EFI_INVALID_PARAMETER;
160 UINT32 Attribs = 0;
161 PartiSelectFilter HandleFilter;
162 // UFS LUN GUIDs
163 EFI_GUID LunGuids[] = {
164 gEfiUfsLU0Guid, gEfiUfsLU1Guid, gEfiUfsLU2Guid, gEfiUfsLU3Guid,
165 gEfiUfsLU4Guid, gEfiUfsLU5Guid, gEfiUfsLU6Guid, gEfiUfsLU7Guid,
166 };
167
168 Attribs |= BLK_IO_SEL_SELECT_ROOT_DEVICE_ONLY;
169 HandleFilter.PartitionType = NULL;
170 HandleFilter.VolumeName = NULL;
171
172 if (Lun == NO_LUN) {
173 HandleFilter.RootDeviceType = &gEfiEmmcUserPartitionGuid;
174 Status =
175 GetBlkIOHandles (Attribs, &HandleFilter, BlockIoHandle, MaxHandles);
176 if (EFI_ERROR (Status)) {
177 DEBUG ((EFI_D_ERROR, "Error getting block IO handle for Emmc\n"));
178 return Status;
179 }
180 } else {
181 HandleFilter.RootDeviceType = &LunGuids[Lun];
182 Status =
183 GetBlkIOHandles (Attribs, &HandleFilter, BlockIoHandle, MaxHandles);
184 if (EFI_ERROR (Status)) {
185 DEBUG ((EFI_D_ERROR, "Error getting block IO handle for Lun:%x\n", Lun));
186 return Status;
187 }
188 }
189
190 return Status;
191}
192
lijuang5b762962019-03-15 20:40:45 +0800193STATIC BOOLEAN IsUpdatePartitionAttributes ()
194{
195 if (CompareMem (PtnEntries, PtnEntriesBak, sizeof (PtnEntries))) {
196 return TRUE;
197 }
198 return FALSE;
199}
200
Lijuan Gaobe74b9e2020-09-21 20:29:27 +0800201UINT64 GetPartitionSize (EFI_BLOCK_IO_PROTOCOL *BlockIo)
202{
203 UINT64 PartitionSize;
204
205 if (!BlockIo) {
206 DEBUG ((EFI_D_ERROR, "Invalid parameter, pleae check BlockIo info!!!\n"));
207 return 0;
208 }
209
210 if (CHECK_ADD64 (BlockIo->Media->LastBlock, 1)) {
211 DEBUG ((EFI_D_ERROR, "Integer overflow while adding LastBlock and 1\n"));
212 return 0;
213 }
214
215 if ((MAX_UINT64 / (BlockIo->Media->LastBlock + 1)) <
216 (UINT64)BlockIo->Media->BlockSize) {
217 DEBUG ((EFI_D_ERROR,
218 "Integer overflow while multiplying LastBlock and BlockSize\n"));
219 return 0;
220 }
221
222 PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize;
223 return PartitionSize;
224}
225
lijuang5b762962019-03-15 20:40:45 +0800226VOID UpdatePartitionAttributes (UINT32 UpdateType)
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700227{
228 UINT32 BlkSz;
229 UINT8 *GptHdr = NULL;
230 UINT8 *GptHdrPtr = NULL;
231 UINTN MaxGptPartEntrySzBytes;
232 UINT32 Offset;
233 UINT32 MaxPtnCount = 0;
234 UINT32 PtnEntrySz = 0;
235 UINT32 i = 0;
236 UINT8 *PtnEntriesPtr;
237 UINT8 *Ptn_Entries;
238 UINT32 CrcVal = 0;
239 UINT32 Iter;
240 UINT32 HdrSz = GPT_HEADER_SIZE;
241 UINT64 DeviceDensity;
242 UINT64 CardSizeSec;
243 EFI_STATUS Status;
244 INT32 Lun;
245 EFI_BLOCK_IO_PROTOCOL *BlockIo = NULL;
246 HandleInfo BlockIoHandle[MAX_HANDLEINF_LST_SIZE];
247 UINT32 MaxHandles = MAX_HANDLEINF_LST_SIZE;
248 CHAR8 BootDeviceType[BOOT_DEV_NAME_SIZE_MAX];
249 UINT32 PartEntriesblocks = 0;
250 BOOLEAN SkipUpdation;
251 UINT64 Attr;
Mukesh Ojha8c4f2722017-11-23 15:09:55 +0530252 struct PartitionEntry *InMemPtnEnt;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700253
lijuang5b762962019-03-15 20:40:45 +0800254 /* The PtnEntries is the same as PtnEntriesBak by default
255 * It needs to update attributes or GUID when PtnEntries is changed
256 */
257 if (!IsUpdatePartitionAttributes ()) {
258 return;
259 }
260
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700261 GetRootDeviceType (BootDeviceType, BOOT_DEV_NAME_SIZE_MAX);
262 for (Lun = 0; Lun < MaxLuns; Lun++) {
263
264 if (!AsciiStrnCmp (BootDeviceType, "EMMC", AsciiStrLen ("EMMC"))) {
265 Status = GetStorageHandle (NO_LUN, BlockIoHandle, &MaxHandles);
266 } else if (!AsciiStrnCmp (BootDeviceType, "UFS", AsciiStrLen ("UFS"))) {
267 Status = GetStorageHandle (Lun, BlockIoHandle, &MaxHandles);
Nagireddy Annem672b53f2019-11-11 13:55:48 +0530268 } else if (!AsciiStrnCmp (BootDeviceType, "NAND", AsciiStrLen ("NAND"))) {
269 if (UpdateType & PARTITION_ATTRIBUTES_MASK) {
270 NandABUpdatePartition (PTN_ENTRIES_TO_MISC);
271 gBS->CopyMem (PtnEntriesBak, PtnEntries, sizeof (PtnEntries));
272 }
273 return;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700274 } else {
275 DEBUG ((EFI_D_ERROR, "Unsupported boot device type\n"));
276 return;
277 }
278
279 if (Status != EFI_SUCCESS) {
280 DEBUG ((EFI_D_ERROR,
lijuang5b762962019-03-15 20:40:45 +0800281 "Failed to get BlkIo for device. MaxHandles:%d - %r\n",
282 MaxHandles, Status));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700283 return;
284 }
285 if (MaxHandles != 1) {
286 DEBUG ((EFI_D_VERBOSE,
287 "Failed to get the BlockIo for device. MaxHandle:%d, %r\n",
288 MaxHandles, Status));
289 continue;
290 }
291
292 BlockIo = BlockIoHandle[0].BlkIo;
Lijuan Gaobe74b9e2020-09-21 20:29:27 +0800293 DeviceDensity = GetPartitionSize (BlockIo);
294 if (!DeviceDensity) {
295 return;
296 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700297 BlkSz = BlockIo->Media->BlockSize;
298 PartEntriesblocks = MAX_PARTITION_ENTRIES_SZ / BlkSz;
299 MaxGptPartEntrySzBytes = (GPT_HDR_BLOCKS + PartEntriesblocks) * BlkSz;
300 CardSizeSec = (DeviceDensity) / BlkSz;
301 Offset = PRIMARY_HDR_LBA;
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530302 GptHdr = AllocateZeroPool (MaxGptPartEntrySzBytes);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700303 if (!GptHdr) {
304 DEBUG ((EFI_D_ERROR, "Unable to Allocate Memory for GptHdr \n"));
305 return;
306 }
307
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700308 GptHdrPtr = GptHdr;
309
310 /* This loop iterates twice to update both primary and backup Gpt*/
311 for (Iter = 0; Iter < 2;
312 Iter++, (Offset = CardSizeSec - MaxGptPartEntrySzBytes / BlkSz)) {
313 SkipUpdation = TRUE;
314 Status = BlockIo->ReadBlocks (BlockIo, BlockIo->Media->MediaId, Offset,
315 MaxGptPartEntrySzBytes, GptHdr);
316
317 if (EFI_ERROR (Status)) {
318 DEBUG ((EFI_D_ERROR, "Unable to read the media \n"));
319 goto Exit;
320 }
321
322 if (Iter == 0x1) {
323 /* This is the back up GPT */
324 Ptn_Entries = GptHdr;
325 GptHdr = GptHdr + ((PartEntriesblocks)*BlkSz);
326 } else
327 /* otherwise we are at the primary gpt */
328 Ptn_Entries = GptHdr + BlkSz;
329
330 PtnEntriesPtr = Ptn_Entries;
331
332 for (i = 0; i < PartitionCount; i++) {
Mukesh Ojha8c4f2722017-11-23 15:09:55 +0530333 InMemPtnEnt = (struct PartitionEntry *)PtnEntriesPtr;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700334 /*If GUID is not present, then it is BlkIo Handle of the Lun. Skip*/
335 if (!(PtnEntries[i].PartEntry.PartitionTypeGUID.Data1)) {
336 DEBUG ((EFI_D_VERBOSE, " Skipping Lun:%d, i=%d\n", Lun, i));
337 continue;
338 }
339
340 if (!AsciiStrnCmp (BootDeviceType, "UFS", AsciiStrLen ("UFS"))) {
341 /* Partition table is populated with entries from lun 0 to max lun.
342 * break out of the loop once we see the partition lun is > current
343 * lun */
344 if (PtnEntries[i].lun > Lun)
345 break;
346 /* Find the entry where the partition table for 'lun' starts and then
347 * update the attributes */
348 if (PtnEntries[i].lun != Lun)
349 continue;
350 }
351 Attr = GET_LLWORD_FROM_BYTE (&PtnEntriesPtr[ATTRIBUTE_FLAG_OFFSET]);
lijuang5b762962019-03-15 20:40:45 +0800352 if (UpdateType & PARTITION_GUID_MASK) {
353 if (CompareMem (&InMemPtnEnt->PartEntry.PartitionTypeGUID,
354 &PtnEntries[i].PartEntry.PartitionTypeGUID,
355 sizeof (EFI_GUID))) {
356 /* Update the partition GUID values */
357 gBS->CopyMem ((VOID *)PtnEntriesPtr,
358 (VOID *)&PtnEntries[i].PartEntry.PartitionTypeGUID,
359 GUID_SIZE);
360 /* Update the PtnEntriesBak for next comparison */
361 gBS->CopyMem (
362 (VOID *)&PtnEntriesBak[i].PartEntry.PartitionTypeGUID,
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700363 (VOID *)&PtnEntries[i].PartEntry.PartitionTypeGUID,
364 GUID_SIZE);
lijuang5b762962019-03-15 20:40:45 +0800365 SkipUpdation = FALSE;
366 }
367 }
368
369 if (UpdateType & PARTITION_ATTRIBUTES_MASK) {
370 /* If GUID is not present, then it is back up GPT, update it
371 * If GUID is present, and the GUID is matched, update it
372 */
373 if (!(InMemPtnEnt->PartEntry.PartitionTypeGUID.Data1) ||
374 !CompareMem (&InMemPtnEnt->PartEntry.PartitionTypeGUID,
375 &PtnEntries[i].PartEntry.PartitionTypeGUID,
376 sizeof (EFI_GUID))) {
377 if (Attr != PtnEntries[i].PartEntry.Attributes) {
378 /* Update the partition attributes */
379 PUT_LONG_LONG (&PtnEntriesPtr[ATTRIBUTE_FLAG_OFFSET],
380 PtnEntries[i].PartEntry.Attributes);
381 /* Update the PtnEntriesBak for next comparison */
382 PtnEntriesBak[i].PartEntry.Attributes =
383 PtnEntries[i].PartEntry.Attributes;
384 SkipUpdation = FALSE;
385 }
386 } else {
387 if (InMemPtnEnt->PartEntry.PartitionTypeGUID.Data1) {
388 DEBUG ((EFI_D_ERROR,
389 "Error in GPT header, GUID is not match!\n"));
390 continue;
391 }
392 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700393 }
394
395 /* point to the next partition entry */
396 PtnEntriesPtr += PARTITION_ENTRY_SIZE;
397 }
398
399 if (SkipUpdation)
400 continue;
401
402 MaxPtnCount = GET_LWORD_FROM_BYTE (&GptHdr[PARTITION_COUNT_OFFSET]);
403 PtnEntrySz = GET_LWORD_FROM_BYTE (&GptHdr[PENTRY_SIZE_OFFSET]);
404
405 if (((UINT64) (MaxPtnCount)*PtnEntrySz) > MAX_PARTITION_ENTRIES_SZ) {
406 DEBUG ((EFI_D_ERROR,
407 "Invalid GPT header fields MaxPtnCount = %x, PtnEntrySz = %x\n",
408 MaxPtnCount, PtnEntrySz));
409 goto Exit;
410 }
411
412 Status = gBS->CalculateCrc32 (Ptn_Entries, ((MaxPtnCount) * (PtnEntrySz)),
413 &CrcVal);
414 if (Status != EFI_SUCCESS) {
415 DEBUG ((EFI_D_ERROR, "Error Calculating CRC32 on the Gpt header: %x\n",
416 Status));
417 goto Exit;
418 }
419
420 PUT_LONG (&GptHdr[PARTITION_CRC_OFFSET], CrcVal);
421
422 /*Write CRC to 0 before we calculate the crc of the GPT header*/
423 CrcVal = 0;
424 PUT_LONG (&GptHdr[HEADER_CRC_OFFSET], CrcVal);
425
426 Status = gBS->CalculateCrc32 (GptHdr, HdrSz, &CrcVal);
427 if (Status != EFI_SUCCESS) {
428 DEBUG ((EFI_D_ERROR, "Error Calculating CRC32 on the Gpt header: %x\n",
429 Status));
430 goto Exit;
431 }
432
433 PUT_LONG (&GptHdr[HEADER_CRC_OFFSET], CrcVal);
434
435 if (Iter == 0x1)
436 /* Write the backup GPT header, which is at an offset of CardSizeSec -
437 * MaxGptPartEntrySzBytes/BlkSz in blocks*/
438 Status =
439 BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, Offset,
440 MaxGptPartEntrySzBytes, (VOID *)Ptn_Entries);
441 else
442 /* Write the primary GPT header, which is at an offset of BlkSz */
443 Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, Offset,
444 MaxGptPartEntrySzBytes, (VOID *)GptHdr);
445
446 if (EFI_ERROR (Status)) {
447 DEBUG ((EFI_D_ERROR, "Error writing primary GPT header: %r\n", Status));
448 goto Exit;
449 }
450 }
451 FreePool (GptHdrPtr);
452 GptHdrPtr = NULL;
453 }
lijuang46df8442017-09-28 19:06:36 +0800454
455Exit:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700456 if (GptHdrPtr) {
457 FreePool (GptHdrPtr);
458 GptHdrPtr = NULL;
459 }
460}
461
462STATIC VOID
463MarkPtnActive (CHAR16 *ActiveSlot)
464{
465 UINT32 i;
466 for (i = 0; i < PartitionCount; i++) {
467 /* Mark all the slots with current ActiveSlot as active */
468 if (StrStr (PtnEntries[i].PartEntry.PartitionName, ActiveSlot))
469 PtnEntries[i].PartEntry.Attributes |= PART_ATT_ACTIVE_VAL;
470 else
471 PtnEntries[i].PartEntry.Attributes &= ~PART_ATT_ACTIVE_VAL;
472 }
473
474 /* Update the partition table */
lijuang5b762962019-03-15 20:40:45 +0800475 UpdatePartitionAttributes (PARTITION_ATTRIBUTES);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700476}
477
478STATIC VOID
479SwapPtnGuid (EFI_PARTITION_ENTRY *p1, EFI_PARTITION_ENTRY *p2)
480{
481 EFI_GUID Temp;
482
483 if (p1 == NULL || p2 == NULL)
484 return;
485 gBS->CopyMem ((VOID *)&Temp, (VOID *)&p1->PartitionTypeGUID,
486 sizeof (EFI_GUID));
487 gBS->CopyMem ((VOID *)&p1->PartitionTypeGUID, (VOID *)&p2->PartitionTypeGUID,
488 sizeof (EFI_GUID));
489 gBS->CopyMem ((VOID *)&p2->PartitionTypeGUID, (VOID *)&Temp,
490 sizeof (EFI_GUID));
491}
492
493STATIC EFI_STATUS GetMultiSlotPartsList (VOID)
494{
495 UINT32 i = 0;
496 UINT32 j = 0;
497 UINT32 Len = 0;
Mukesh Ojha28736ad2017-11-23 14:34:03 +0530498 UINT32 PtnLen = 0;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700499 CHAR16 *SearchString = NULL;
500 struct BootPartsLinkedList *TempNode = NULL;
501
502 for (i = 0; i < PartitionCount; i++) {
503 SearchString = PtnEntries[i].PartEntry.PartitionName;
504 if (!SearchString[0])
505 continue;
506
507 for (j = i + 1; j < PartitionCount; j++) {
508 if (!PtnEntries[j].PartEntry.PartitionName[0])
509 continue;
510 Len = StrLen (SearchString);
Mukesh Ojha28736ad2017-11-23 14:34:03 +0530511 PtnLen = StrLen (PtnEntries[j].PartEntry.PartitionName);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700512
513 /*Need to compare till "boot_"a hence skip last Char from StrLen value*/
Mukesh Ojha28736ad2017-11-23 14:34:03 +0530514 if ((PtnLen == Len) &&
515 !StrnCmp (PtnEntries[j].PartEntry.PartitionName,
516 SearchString, Len - 1) &&
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700517 (StrStr (SearchString, (CONST CHAR16 *)L"_a") ||
Mukesh Ojha28736ad2017-11-23 14:34:03 +0530518 StrStr (SearchString, (CONST CHAR16 *)L"_b"))) {
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530519 TempNode = AllocateZeroPool (sizeof (struct BootPartsLinkedList));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700520 if (TempNode) {
521 /*Skip _a/_b from partition name*/
522 StrnCpyS (TempNode->PartName, sizeof (TempNode->PartName),
523 SearchString, Len - 2);
524 TempNode->Next = HeadNode;
525 HeadNode = TempNode;
526 } else {
527 DEBUG ((EFI_D_ERROR,
528 "Unable to Allocate Memory for MultiSlot Partition list\n"));
529 return EFI_OUT_OF_RESOURCES;
530 }
531 break;
532 }
lijuang46df8442017-09-28 19:06:36 +0800533 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700534 }
535 return EFI_SUCCESS;
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530536}
537
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700538STATIC VOID
539SwitchPtnSlots (CONST CHAR16 *SetActive)
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530540{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700541 UINT32 i;
542 struct PartitionEntry *PtnCurrent = NULL;
543 struct PartitionEntry *PtnNew = NULL;
544 CHAR16 CurSlot[BOOT_PART_SIZE];
545 CHAR16 NewSlot[BOOT_PART_SIZE];
546 CHAR16 SetInactive[MAX_SLOT_SUFFIX_SZ];
547 UINT32 UfsBootLun = 0;
548 BOOLEAN UfsGet = TRUE;
549 BOOLEAN UfsSet = FALSE;
550 struct BootPartsLinkedList *TempNode = NULL;
551 EFI_STATUS Status;
552 CHAR8 BootDeviceType[BOOT_DEV_NAME_SIZE_MAX];
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530553
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700554 /* Create the partition name string for active and non active slots*/
555 if (!StrnCmp (SetActive, (CONST CHAR16 *)L"_a",
556 StrLen ((CONST CHAR16 *)L"_a")))
557 StrnCpyS (SetInactive, MAX_SLOT_SUFFIX_SZ, (CONST CHAR16 *)L"_b",
558 StrLen ((CONST CHAR16 *)L"_b"));
559 else
560 StrnCpyS (SetInactive, MAX_SLOT_SUFFIX_SZ, (CONST CHAR16 *)L"_a",
561 StrLen ((CONST CHAR16 *)L"_a"));
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530562
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700563 if (!HeadNode) {
564 Status = GetMultiSlotPartsList ();
565 if (Status != EFI_SUCCESS) {
566 DEBUG ((EFI_D_INFO, "Unable to get GetMultiSlotPartsList\n"));
567 return;
568 }
569 }
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530570
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700571 for (TempNode = HeadNode; TempNode; TempNode = TempNode->Next) {
572 gBS->SetMem (CurSlot, BOOT_PART_SIZE, 0);
573 gBS->SetMem (NewSlot, BOOT_PART_SIZE, 0);
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530574
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700575 StrnCpyS (CurSlot, BOOT_PART_SIZE, TempNode->PartName,
576 StrLen (TempNode->PartName));
577 StrnCatS (CurSlot, BOOT_PART_SIZE, SetInactive, StrLen (SetInactive));
Vijay Kumar Pendotia7e72a02016-11-11 15:36:56 +0530578
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700579 StrnCpyS (NewSlot, BOOT_PART_SIZE, TempNode->PartName,
580 StrLen (TempNode->PartName));
581 StrnCatS (NewSlot, BOOT_PART_SIZE, SetActive, StrLen (SetActive));
Vijay Kumar Pendotia7e72a02016-11-11 15:36:56 +0530582
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700583 /* Find the pointer to partition table entry for active and non-active
584 * slots*/
585 for (i = 0; i < PartitionCount; i++) {
586 if (!StrnCmp (PtnEntries[i].PartEntry.PartitionName, CurSlot,
587 StrLen (CurSlot))) {
588 PtnCurrent = &PtnEntries[i];
589 } else if (!StrnCmp (PtnEntries[i].PartEntry.PartitionName, NewSlot,
590 StrLen (NewSlot))) {
591 PtnNew = &PtnEntries[i];
592 }
593 }
594 /* Swap the guids for the slots */
595 SwapPtnGuid (&PtnCurrent->PartEntry, &PtnNew->PartEntry);
596 PtnCurrent = PtnNew = NULL;
597 }
Vijay Kumar Pendotia7e72a02016-11-11 15:36:56 +0530598
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700599 GetRootDeviceType (BootDeviceType, BOOT_DEV_NAME_SIZE_MAX);
600 if (!AsciiStrnCmp (BootDeviceType, "UFS", AsciiStrLen ("UFS"))) {
601 UfsGetSetBootLun (&UfsBootLun, UfsGet);
602 // Special case for XBL is to change the bootlun instead of swapping the
603 // guid
604 if (UfsBootLun == 0x1 &&
605 !StrnCmp (SetActive, (CONST CHAR16 *)L"_b",
606 StrLen ((CONST CHAR16 *)L"_b"))) {
607 DEBUG ((EFI_D_INFO, "Switching the boot lun from 1 to 2\n"));
608 UfsBootLun = 0x2;
609 } else if (UfsBootLun == 0x2 &&
610 !StrnCmp (SetActive, (CONST CHAR16 *)L"_a",
611 StrLen ((CONST CHAR16 *)L"_a"))) {
612 DEBUG ((EFI_D_INFO, "Switching the boot lun from 2 to 1\n"));
613 UfsBootLun = 0x1;
614 }
615 UfsGetSetBootLun (&UfsBootLun, UfsSet);
616 }
lijuang5b762962019-03-15 20:40:45 +0800617
618 UpdatePartitionAttributes (PARTITION_GUID);
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530619}
620
621EFI_STATUS
lijuangf0bbcad2017-08-16 16:59:18 +0800622EnumeratePartitions (VOID)
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530623{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700624 EFI_STATUS Status;
625 PartiSelectFilter HandleFilter;
626 UINT32 Attribs = 0;
627 UINT32 i;
628 // UFS LUN GUIDs
629 EFI_GUID LunGuids[] = {
630 gEfiUfsLU0Guid, gEfiUfsLU1Guid, gEfiUfsLU2Guid, gEfiUfsLU3Guid,
631 gEfiUfsLU4Guid, gEfiUfsLU5Guid, gEfiUfsLU6Guid, gEfiUfsLU7Guid,
632 };
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530633
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700634 gBS->SetMem ((VOID *)Ptable, (sizeof (struct StoragePartInfo) * MAX_LUNS), 0);
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530635
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700636 /* By default look for emmc partitions if not found look for UFS */
637 Attribs |= BLK_IO_SEL_MATCH_ROOT_DEVICE;
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530638
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700639 Ptable[0].MaxHandles = ARRAY_SIZE (Ptable[0].HandleInfoList);
640 HandleFilter.PartitionType = NULL;
641 HandleFilter.VolumeName = NULL;
642 HandleFilter.RootDeviceType = &gEfiNandUserPartitionGuid;
Jeevan Shriram749ea922017-08-15 13:50:12 -0700643
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700644 Status =
645 GetBlkIOHandles (Attribs, &HandleFilter, &Ptable[0].HandleInfoList[0],
646 &Ptable[0].MaxHandles);
647 /* For Emmc/NAND devices the Lun concept does not exist, we will always one
648 * lun and the lun number is '0'
649 * to have the partition selection implementation same acros
650 */
651 if (Status == EFI_SUCCESS && Ptable[0].MaxHandles > 0) {
652 MaxLuns = 1;
653 return Status;
654 }
Jeevan Shriram749ea922017-08-15 13:50:12 -0700655
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700656 Ptable[0].MaxHandles = ARRAY_SIZE (Ptable[0].HandleInfoList);
657 HandleFilter.PartitionType = NULL;
658 HandleFilter.VolumeName = NULL;
659 HandleFilter.RootDeviceType = &gEfiEmmcUserPartitionGuid;
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530660
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700661 Status =
662 GetBlkIOHandles (Attribs, &HandleFilter, &Ptable[0].HandleInfoList[0],
663 &Ptable[0].MaxHandles);
664 if (Status == EFI_SUCCESS && Ptable[0].MaxHandles > 0) {
665 MaxLuns = 1;
666 }
667 /* If the media is not emmc then look for UFS */
668 else if (EFI_ERROR (Status) || Ptable[0].MaxHandles == 0) {
669 /* By default max 8 luns are supported but HW could be configured to use
670 * only few of them or all of them
671 * Based on the information read update the MaxLuns to reflect the max
672 * supported luns */
673 for (i = 0; i < MAX_LUNS; i++) {
674 Ptable[i].MaxHandles = ARRAY_SIZE (Ptable[i].HandleInfoList);
675 HandleFilter.PartitionType = NULL;
676 HandleFilter.VolumeName = NULL;
677 HandleFilter.RootDeviceType = &LunGuids[i];
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530678
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700679 Status =
680 GetBlkIOHandles (Attribs, &HandleFilter, &Ptable[i].HandleInfoList[0],
681 &Ptable[i].MaxHandles);
682 /* If we fail to get block for a lun that means the lun is not configured
683 * and unsed, ignore the error
684 * and continue with the next Lun */
685 if (EFI_ERROR (Status)) {
686 DEBUG ((EFI_D_ERROR,
687 "Error getting block IO handle for %d lun, Lun may be unused\n",
688 i));
689 continue;
690 }
691 }
692 MaxLuns = i;
693 } else {
694 DEBUG ((EFI_D_ERROR, "Error populating block IO handles\n"));
695 return EFI_NOT_FOUND;
696 }
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530697
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700698 return Status;
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530699}
700
701/*Function to provide has-slot info
702 *Pname: the partition name
703 *return: 1 or 0.
704 */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700705BOOLEAN
706PartitionHasMultiSlot (CONST CHAR16 *Pname)
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530707{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700708 UINT32 i;
709 UINT32 SlotCount = 0;
710 UINT32 Len = StrLen (Pname);
Vijay Kumar Pendotic3e0a4f2016-08-27 03:31:40 +0530711
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700712 for (i = 0; i < PartitionCount; i++) {
713 if (!(StrnCmp (PtnEntries[i].PartEntry.PartitionName, Pname, Len))) {
714 if (PtnEntries[i].PartEntry.PartitionName[Len] == L'_' &&
715 (PtnEntries[i].PartEntry.PartitionName[Len + 1] == L'a' ||
716 PtnEntries[i].PartEntry.PartitionName[Len + 1] == L'b'))
717 if (++SlotCount > MIN_SLOTS) {
718 return TRUE;
Zhen Kong4c788f52017-07-19 16:51:58 -0700719 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700720 }
721 }
722 return FALSE;
Zhen Kong4c788f52017-07-19 16:51:58 -0700723}
724
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700725VOID FindPtnActiveSlot (VOID)
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700726{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700727 Slot ActiveSlot = {{0}};
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700728
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700729 GetActiveSlot (&ActiveSlot);
730 return;
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700731}
732
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700733STATIC UINT32
734PartitionVerifyMbrSignature (UINT32 Sz, UINT8 *Gpt)
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700735{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700736 if ((MBR_SIGNATURE + 1) >= Sz) {
737 DEBUG ((EFI_D_ERROR, "Gpt Image size is invalid\n"));
738 return FAILURE;
739 }
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700740
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700741 /* Check for the signature */
742 if ((Gpt[MBR_SIGNATURE] != MBR_SIGNATURE_BYTE_0) ||
743 (Gpt[MBR_SIGNATURE + 1] != MBR_SIGNATURE_BYTE_1)) {
744 DEBUG ((EFI_D_ERROR, "MBR signature do not match\n"));
745 return FAILURE;
746 }
747 return SUCCESS;
748}
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700749
Prakruthi Deepak Heragud84bac22019-09-26 16:02:18 -0700750UINT32
751PartitionVerifyMibibImage (UINT8 *Image)
752{
753
754 /* Check for the MIBIB Magic */
755 if ((((UINT32 *)Image)[0] != MIBIB_MAGIC1) ||
756 (((UINT32 *)Image)[1] != MIBIB_MAGIC2)) {
757 DEBUG ((EFI_D_ERROR, "Mibib Magic do not match\n"));
758 return FAILURE;
759 }
760 return SUCCESS;
761}
762
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700763STATIC UINT32
764MbrGetPartitionType (UINT32 Sz, UINT8 *Gpt, UINT32 *Ptype)
765{
766 UINT32 PtypeOffset = MBR_PARTITION_RECORD + OS_TYPE;
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700767
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700768 if (Sz <= PtypeOffset) {
769 DEBUG ((EFI_D_ERROR,
770 "Input gpt image does not have gpt partition record data\n"));
771 return FAILURE;
772 }
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700773
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700774 *Ptype = Gpt[PtypeOffset];
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700775
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700776 return SUCCESS;
777}
Shivaprasad Hongalc017e812017-04-26 16:15:27 -0700778
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700779STATIC UINT32
780PartitionGetType (UINT32 Sz, UINT8 *Gpt, UINT32 *Ptype)
781{
782 UINT32 Ret;
783
784 Ret = PartitionVerifyMbrSignature (Sz, Gpt);
785 if (!Ret) {
786 /* MBR signature match, this coulb be MBR, MBR + EBR or GPT */
787 Ret = MbrGetPartitionType (Sz, Gpt, Ptype);
788 if (!Ret) {
789 if (*Ptype == GPT_PROTECTIVE)
790 *Ptype = PARTITION_TYPE_GPT;
791 else
792 *Ptype = PARTITION_TYPE_MBR;
793 }
794 } else {
795 /* This could be GPT back up */
796 *Ptype = PARTITION_TYPE_GPT_BACKUP;
797 Ret = SUCCESS;
798 }
799
800 return Ret;
801}
802
803STATIC UINT32
804ParseGptHeader (struct GptHeaderData *GptHeader,
805 UINT8 *GptBuffer,
806 UINT64 DeviceDensity,
807 UINT32 BlkSz)
808{
809 UINT32 CrcOrig;
810 UINT32 CrcVal;
811 UINT32 CurrentLba;
812 EFI_STATUS Status;
813
814 if (((UINT32 *)GptBuffer)[0] != GPT_SIGNATURE_2 ||
815 ((UINT32 *)GptBuffer)[1] != GPT_SIGNATURE_1) {
816 DEBUG ((EFI_D_ERROR, "Gpt signature is not correct\n"));
817 return FAILURE;
818 }
819
820 GptHeader->HeaderSz = GET_LWORD_FROM_BYTE (&GptBuffer[HEADER_SIZE_OFFSET]);
821 /* Validate the header size */
822 if (GptHeader->HeaderSz < GPT_HEADER_SIZE) {
823 DEBUG ((EFI_D_ERROR, "GPT Header size is too small: %u\n",
824 GptHeader->HeaderSz));
825 return FAILURE;
826 }
827
828 if (GptHeader->HeaderSz > BlkSz) {
829 DEBUG ((EFI_D_ERROR, "GPT Header is too large: %u\n", GptHeader->HeaderSz));
830 return FAILURE;
831 }
832
833 CrcOrig = GET_LWORD_FROM_BYTE (&GptBuffer[HEADER_CRC_OFFSET]);
834 /* CRC value is computed by setting this field to 0, and computing the 32-bit
835 * CRC for HeaderSize bytes */
836 CrcVal = 0;
837 PUT_LONG (&GptBuffer[HEADER_CRC_OFFSET], CrcVal);
838
839 Status = gBS->CalculateCrc32 (GptBuffer, GptHeader->HeaderSz, &CrcVal);
840 if (Status != EFI_SUCCESS) {
841 DEBUG ((EFI_D_ERROR, "Error Calculating CRC32 on the Gpt header: %x\n",
842 Status));
843 return FAILURE;
844 }
845
846 if (CrcVal != CrcOrig) {
847 DEBUG ((EFI_D_ERROR, "Header CRC mismatch CrcVal = %u and CrcOrig = %u\n",
848 CrcVal, CrcOrig));
849 return FAILURE;
850 } else
851 PUT_LONG (&GptBuffer[HEADER_CRC_OFFSET], CrcVal);
852
853 CurrentLba = GET_LLWORD_FROM_BYTE (&GptBuffer[PRIMARY_HEADER_OFFSET]);
854 GptHeader->FirstUsableLba =
855 GET_LLWORD_FROM_BYTE (&GptBuffer[FIRST_USABLE_LBA_OFFSET]);
856 GptHeader->MaxPtCnt =
857 GET_LWORD_FROM_BYTE (&GptBuffer[PARTITION_COUNT_OFFSET]);
858 GptHeader->PartEntrySz = GET_LWORD_FROM_BYTE (&GptBuffer[PENTRY_SIZE_OFFSET]);
859 GptHeader->LastUsableLba =
860 GET_LLWORD_FROM_BYTE (&GptBuffer[LAST_USABLE_LBA_OFFSET]);
861 if (!ParseSecondaryGpt) {
862 if (CurrentLba != GPT_LBA) {
863 DEBUG ((EFI_D_ERROR, "GPT first usable LBA mismatch\n"));
864 return FAILURE;
865 }
866 }
867
868 /* Check for first lba should be within valid range */
869 if (GptHeader->FirstUsableLba > (DeviceDensity / BlkSz)) {
870 DEBUG ((EFI_D_ERROR, "FirstUsableLba: %u out of Device capacity\n",
871 GptHeader->FirstUsableLba));
872 return FAILURE;
873 }
874
875 /* Check for Last lba should be within valid range */
876 if (GptHeader->LastUsableLba > (DeviceDensity / BlkSz)) {
877 DEBUG ((EFI_D_ERROR, "LastUsableLba: %u out of device capacity\n",
878 GptHeader->LastUsableLba));
879 return FAILURE;
880 }
881
882 if (GptHeader->PartEntrySz != GPT_PART_ENTRY_SIZE) {
883 DEBUG ((EFI_D_ERROR, "Invalid partition entry size: %u\n",
884 GptHeader->PartEntrySz));
885 return FAILURE;
886 }
887
888 if (GptHeader->MaxPtCnt >
889 (MIN_PARTITION_ARRAY_SIZE / (GptHeader->PartEntrySz))) {
890 DEBUG ((EFI_D_ERROR, "Invalid Max Partition Count: %u\n",
891 GptHeader->MaxPtCnt));
892 return FAILURE;
893 }
894
895 /* Todo: Check CRC during reading partition table*/
896 if (!FlashingGpt) {
897 }
898
899 return SUCCESS;
900}
901
902STATIC UINT32
903PatchGpt (UINT8 *Gpt,
904 UINT64 DeviceDensity,
905 UINT32 PartEntryArrSz,
906 struct GptHeaderData *GptHeader,
907 UINT32 BlkSz)
908{
909 UINT8 *PrimaryGptHeader;
910 UINT8 *SecondaryGptHeader;
jianzhou8e3a2302018-07-05 18:07:40 +0800911 //define as 64 bit unsigned int
912 UINT64 *LastPartitionEntry;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700913 UINT64 NumSectors;
914 UINT32 Offset;
915 UINT32 TotalPart = 0;
916 UINT32 LastPartOffset;
917 UINT8 *PartitionEntryArrStart;
918 UINT32 CrcVal;
919 EFI_STATUS Status;
Bhanuprakash Modem937fc4a2018-06-12 16:11:26 +0530920 UINT32 PtnEntryBlks = (MAX_PARTITION_ENTRIES_SZ / BlkSz) + GPT_HDR_BLOCKS;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700921 NumSectors = DeviceDensity / BlkSz;
922
923 /* Update the primary and backup GPT header offset with the sector location */
924 PrimaryGptHeader = (Gpt + BlkSz);
925 /* Patch primary GPT */
926 PUT_LONG_LONG (PrimaryGptHeader + BACKUP_HEADER_OFFSET,
927 (UINT64) (NumSectors - 1));
928 PUT_LONG_LONG (PrimaryGptHeader + LAST_USABLE_LBA_OFFSET,
Bhanuprakash Modem937fc4a2018-06-12 16:11:26 +0530929 (UINT64) (NumSectors - (PtnEntryBlks + 1)));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700930
931 /* Patch Backup GPT */
932 Offset = (2 * PartEntryArrSz);
933 SecondaryGptHeader = Offset + BlkSz + PrimaryGptHeader;
934 PUT_LONG_LONG (SecondaryGptHeader + PRIMARY_HEADER_OFFSET, (UINT64)1);
935 PUT_LONG_LONG (SecondaryGptHeader + LAST_USABLE_LBA_OFFSET,
Bhanuprakash Modem937fc4a2018-06-12 16:11:26 +0530936 (UINT64) (NumSectors - (PtnEntryBlks + 1)));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700937 PUT_LONG_LONG (SecondaryGptHeader + PARTITION_ENTRIES_OFFSET,
Bhanuprakash Modem937fc4a2018-06-12 16:11:26 +0530938 (UINT64) (NumSectors - (PtnEntryBlks)));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700939
940 /* Patch the last partition */
jianzhou8e3a2302018-07-05 18:07:40 +0800941 LastPartitionEntry = (UINT64 *)
942 (PrimaryGptHeader + BlkSz + TotalPart * PARTITION_ENTRY_SIZE);
943
944 //need check 128 bit for GUID
Mukesh Ojha3ede8722018-04-10 14:32:26 +0530945 while ((TotalPart < GptHeader->MaxPtCnt) &&
jianzhou8e3a2302018-07-05 18:07:40 +0800946 ((*LastPartitionEntry != 0) ||
947 (*(LastPartitionEntry + 1) != 0))) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700948 TotalPart++;
jianzhou8e3a2302018-07-05 18:07:40 +0800949 LastPartitionEntry = (UINT64 *)
950 (PrimaryGptHeader + BlkSz + TotalPart * PARTITION_ENTRY_SIZE);
Mukesh Ojha3ede8722018-04-10 14:32:26 +0530951 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700952
953 LastPartOffset =
954 (TotalPart - 1) * PARTITION_ENTRY_SIZE + PARTITION_ENTRY_LAST_LBA;
955
956 PUT_LONG_LONG (PrimaryGptHeader + BlkSz + LastPartOffset,
Bhanuprakash Modem937fc4a2018-06-12 16:11:26 +0530957 (UINT64) (NumSectors - (PtnEntryBlks + 1)));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700958 PUT_LONG_LONG (PrimaryGptHeader + BlkSz + LastPartOffset + PartEntryArrSz,
Bhanuprakash Modem937fc4a2018-06-12 16:11:26 +0530959 (UINT64) (NumSectors - (PtnEntryBlks + 1)));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700960
961 /* Update CRC of the partition entry array for both headers */
962 PartitionEntryArrStart = PrimaryGptHeader + BlkSz;
963 Status = gBS->CalculateCrc32 (PartitionEntryArrStart,
964 (GptHeader->MaxPtCnt * GptHeader->PartEntrySz),
965 &CrcVal);
966 if (EFI_ERROR (Status)) {
967 DEBUG (
968 (EFI_D_ERROR, "Error calculating CRC for primary partition entry\n"));
969 return FAILURE;
970 }
971 PUT_LONG (PrimaryGptHeader + PARTITION_CRC_OFFSET, CrcVal);
972
973 Status = gBS->CalculateCrc32 (PartitionEntryArrStart + PartEntryArrSz,
974 (GptHeader->MaxPtCnt * GptHeader->PartEntrySz),
975 &CrcVal);
976 if (EFI_ERROR (Status)) {
977 DEBUG (
978 (EFI_D_ERROR, "Error calculating CRC for secondary partition entry\n"));
979 return FAILURE;
980 }
981 PUT_LONG (SecondaryGptHeader + PARTITION_CRC_OFFSET, CrcVal);
982
983 /* Clear Header CRC field values & recalculate */
984 PUT_LONG (PrimaryGptHeader + HEADER_CRC_OFFSET, 0);
985 Status = gBS->CalculateCrc32 (PrimaryGptHeader, GPT_HEADER_SIZE, &CrcVal);
986 if (EFI_ERROR (Status)) {
987 DEBUG ((EFI_D_ERROR, "Error calculating CRC for primary gpt header\n"));
988 return FAILURE;
989 }
990 PUT_LONG (PrimaryGptHeader + HEADER_CRC_OFFSET, CrcVal);
991 PUT_LONG (SecondaryGptHeader + HEADER_CRC_OFFSET, 0);
992 Status = gBS->CalculateCrc32 (SecondaryGptHeader, GPT_HEADER_SIZE, &CrcVal);
993 if (EFI_ERROR (Status)) {
994 DEBUG ((EFI_D_ERROR, "Error calculating CRC for secondary gpt header\n"));
995 return FAILURE;
996 }
997 PUT_LONG (SecondaryGptHeader + HEADER_CRC_OFFSET, CrcVal);
998
999 return SUCCESS;
1000}
1001
1002STATIC UINT32
1003WriteGpt (INT32 Lun, UINT32 Sz, UINT8 *Gpt)
1004{
1005 UINT32 Ret = 1;
1006 struct GptHeaderData GptHeader;
1007 UINT8 *PartEntryArrSt;
1008 UINT32 Offset;
1009 UINT32 PartEntryArrSz;
1010 UINT64 DeviceDensity;
1011 UINT32 BlkSz;
1012 UINT8 *PrimaryGptHdr = NULL;
1013 UINT8 *SecondaryGptHdr = NULL;
1014 EFI_STATUS Status;
1015 UINTN BackUpGptLba;
1016 UINTN PartitionEntryLba;
1017 EFI_BLOCK_IO_PROTOCOL *BlockIo = NULL;
1018 HandleInfo BlockIoHandle[MAX_HANDLEINF_LST_SIZE];
1019 UINT32 MaxHandles = MAX_HANDLEINF_LST_SIZE;
1020
1021 Ret = GetStorageHandle (Lun, BlockIoHandle, &MaxHandles);
1022 if (Ret || (MaxHandles != 1)) {
1023 DEBUG ((EFI_D_ERROR, "Failed to get the BlockIo for the device\n"));
1024 return Ret;
1025 }
1026
1027 BlockIo = BlockIoHandle[0].BlkIo;
Lijuan Gaobe74b9e2020-09-21 20:29:27 +08001028 DeviceDensity = GetPartitionSize (BlockIo);
1029 if (!DeviceDensity) {
1030 return FAILURE;
1031 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001032 BlkSz = BlockIo->Media->BlockSize;
1033
Lijuan Gaoe53c24c2020-09-28 18:43:16 +08001034 /* Verity that passed block has valid GPT primary header
1035 * Sz is from mNumDataBytes and it will check at CmdDownload
1036 * if it is mNumDataBytes > MaxDownLoadSize it will fail early and
1037 * will not cause any oob
1038 */
1039 if (Sz <= BlkSz * 2) {
1040 DEBUG ((EFI_D_ERROR, "Gpt Image size is invalid!\n"));
1041 return FAILURE;
1042 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001043 PrimaryGptHdr = (Gpt + BlkSz);
1044 Ret = ParseGptHeader (&GptHeader, PrimaryGptHdr, DeviceDensity, BlkSz);
1045 if (Ret) {
1046 DEBUG ((EFI_D_ERROR, "GPT: Error processing primary GPT header\n"));
1047 return Ret;
1048 }
1049
1050 /* Check if a valid back up GPT is present */
1051 PartEntryArrSz = GptHeader.PartEntrySz * GptHeader.MaxPtCnt;
1052 if (PartEntryArrSz < MIN_PARTITION_ARRAY_SIZE)
1053 PartEntryArrSz = MIN_PARTITION_ARRAY_SIZE;
1054
1055 /* Back up partition is stored in the reverse order with back GPT, followed by
1056 * part entries, find the offset to back up GPT */
1057 Offset = (2 * PartEntryArrSz);
Lijuan Gaoe53c24c2020-09-28 18:43:16 +08001058 if (Sz < (Offset + (BlkSz * 3))) {
1059 DEBUG ((EFI_D_ERROR, "Gpt Image size is invalid!!\n"));
1060 return FAILURE;
1061 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001062 SecondaryGptHdr = Offset + BlkSz + PrimaryGptHdr;
1063 ParseSecondaryGpt = TRUE;
1064
1065 Ret = ParseGptHeader (&GptHeader, SecondaryGptHdr, DeviceDensity, BlkSz);
1066 if (Ret) {
1067 DEBUG ((EFI_D_ERROR, "GPT: Error processing backup GPT header\n"));
1068 return Ret;
1069 }
1070
1071 Ret = PatchGpt (Gpt, DeviceDensity, PartEntryArrSz, &GptHeader, BlkSz);
1072 if (Ret) {
1073 DEBUG ((EFI_D_ERROR, "Failed to patch GPT\n"));
1074 return Ret;
1075 }
1076 /* Erase the entire card */
1077 Status = ErasePartition (BlockIo, BlockIoHandle[0].Handle);
1078 if (Status != EFI_SUCCESS) {
1079 DEBUG ((EFI_D_ERROR, "Error erasing the storage device: %r\n", Status));
1080 return FAILURE;
1081 }
1082
1083 /* write the protective MBR */
1084 Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, 0, BlkSz,
1085 (VOID *)Gpt);
1086 if (EFI_ERROR (Status)) {
1087 DEBUG ((EFI_D_ERROR, "Error writing protective MBR: %x\n", Status));
1088 return FAILURE;
1089 }
1090
1091 /* Write the primary GPT header, which is at an offset of BlkSz */
1092 Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, 1, BlkSz,
1093 (VOID *)PrimaryGptHdr);
1094 if (EFI_ERROR (Status)) {
1095 DEBUG ((EFI_D_ERROR, "Error writing primary GPT header: %r\n", Status));
1096 return FAILURE;
1097 }
1098
1099 /* Write the back up GPT header */
1100 BackUpGptLba = GET_LLWORD_FROM_BYTE (&PrimaryGptHdr[BACKUP_HEADER_OFFSET]);
1101 Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, BackUpGptLba,
1102 BlkSz, (VOID *)SecondaryGptHdr);
1103 if (EFI_ERROR (Status)) {
1104 DEBUG ((EFI_D_ERROR, "Error writing secondary GPT header: %x\n", Status));
1105 return FAILURE;
1106 }
1107
1108 /* write Partition Entries for primary partition table*/
1109 PartEntryArrSt = PrimaryGptHdr + BlkSz;
1110 PartitionEntryLba =
1111 GET_LLWORD_FROM_BYTE (&PrimaryGptHdr[PARTITION_ENTRIES_OFFSET]);
1112 Status =
1113 BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, PartitionEntryLba,
1114 PartEntryArrSz, (VOID *)PartEntryArrSt);
1115 if (EFI_ERROR (Status)) {
1116 DEBUG ((EFI_D_ERROR,
1117 "Error writing partition entries array for Primary Table: %x\n",
1118 Status));
1119 return FAILURE;
1120 }
1121
1122 /* write Partition Entries for secondary partition table*/
1123 PartEntryArrSt = PrimaryGptHdr + BlkSz + PartEntryArrSz;
1124 PartitionEntryLba =
1125 GET_LLWORD_FROM_BYTE (&SecondaryGptHdr[PARTITION_ENTRIES_OFFSET]);
1126 Status =
1127 BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, PartitionEntryLba,
1128 PartEntryArrSz, (VOID *)PartEntryArrSt);
1129 if (EFI_ERROR (Status)) {
1130 DEBUG ((EFI_D_ERROR,
1131 "Error writing partition entries array for Secondary Table: %x\n",
1132 Status));
1133 return FAILURE;
1134 }
1135 FlashingGpt = 0;
Lijuan Gaoe53c24c2020-09-28 18:43:16 +08001136 gBS->SetMem ((VOID *)Gpt, Sz, 0x0);
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001137
1138 DEBUG ((EFI_D_ERROR, "Updated Partition Table Successfully\n"));
1139 return SUCCESS;
1140}
1141
1142EFI_STATUS
1143UpdatePartitionTable (UINT8 *GptImage,
1144 UINT32 Sz,
1145 INT32 Lun,
1146 struct StoragePartInfo *Ptable)
1147{
1148 EFI_STATUS Status = EFI_SUCCESS;
1149 UINT32 Ptype;
1150 UINT32 Ret;
1151
1152 /* Check if the partition type is GPT */
1153 Ret = PartitionGetType (Sz, GptImage, &Ptype);
1154 if (Ret != 0) {
1155 DEBUG (
1156 (EFI_D_ERROR, "Failed to get partition type from input gpt image\n"));
1157 return EFI_NOT_FOUND;
1158 }
1159
1160 switch (Ptype) {
1161 case PARTITION_TYPE_GPT:
1162 DEBUG ((EFI_D_INFO, "Updating GPT partition\n"));
1163 FlashingGpt = TRUE;
1164 Ret = WriteGpt (Lun, Sz, GptImage);
1165 if (Ret != 0) {
1166 DEBUG ((EFI_D_ERROR, "Failed to write Gpt partition: %x\n", Ret));
1167 return EFI_VOLUME_CORRUPTED;
1168 }
1169 break;
1170 default:
1171 DEBUG ((EFI_D_ERROR, "Invalid Partition type: %x\n", Ptype));
1172 Status = EFI_UNSUPPORTED;
1173 break;
1174 }
1175
1176 return Status;
1177}
1178
1179STATIC CONST struct PartitionEntry *
1180GetPartitionEntry (CHAR16 *Partition)
1181{
1182 INT32 Index = GetPartitionIndex (Partition);
1183
1184 if (Index == INVALID_PTN) {
1185 DEBUG ((EFI_D_ERROR, "GetPartitionEntry: No partition entry for "
1186 "%s, invalid index\n",
1187 Partition));
1188 return NULL;
1189 }
1190 return &PtnEntries[Index];
1191}
1192
1193STATIC struct PartitionEntry *
1194GetBootPartitionEntry (Slot *BootSlot)
1195{
1196 INT32 Index = INVALID_PTN;
1197
1198 if (StrnCmp ((CONST CHAR16 *)L"_a", BootSlot->Suffix,
1199 StrLen (BootSlot->Suffix)) == 0) {
1200 Index = GetPartitionIndex ((CHAR16 *)L"boot_a");
1201 } else if (StrnCmp ((CONST CHAR16 *)L"_b", BootSlot->Suffix,
1202 StrLen (BootSlot->Suffix)) == 0) {
1203 Index = GetPartitionIndex ((CHAR16 *)L"boot_b");
1204 } else {
1205 DEBUG ((EFI_D_ERROR, "GetBootPartitionEntry: No boot partition "
1206 "entry for slot %s\n",
1207 BootSlot->Suffix));
1208 return NULL;
1209 }
1210
1211 if (Index == INVALID_PTN) {
1212 DEBUG ((EFI_D_ERROR, "GetBootPartitionEntry: No boot partition entry "
1213 "for slot %s, invalid index\n",
1214 BootSlot->Suffix));
1215 return NULL;
1216 }
1217 return &PtnEntries[Index];
1218}
1219
1220BOOLEAN IsCurrentSlotBootable (VOID)
1221{
1222 Slot CurrentSlot = {{0}};
1223 struct PartitionEntry *BootPartition = NULL;
1224 EFI_STATUS Status = GetActiveSlot (&CurrentSlot);
1225
1226 if (Status != EFI_SUCCESS) {
1227 DEBUG ((EFI_D_ERROR, "IsCurrentSlotBootable: no active slots found!\n"));
1228 return FALSE;
1229 }
1230
1231 BootPartition = GetBootPartitionEntry (&CurrentSlot);
1232 if (BootPartition == NULL) {
1233 DEBUG ((EFI_D_ERROR, "IsCurrentSlotBootable: No boot partition "
1234 "entry for slot %s\n",
1235 CurrentSlot.Suffix));
1236 return FALSE;
1237 }
1238 DEBUG ((EFI_D_VERBOSE, "Slot suffix %s Part Attr 0x%lx\n", CurrentSlot.Suffix,
1239 BootPartition->PartEntry.Attributes));
1240
1241 if (!(BootPartition->PartEntry.Attributes & PART_ATT_UNBOOTABLE_VAL) &&
1242 BootPartition->PartEntry.Attributes & PART_ATT_SUCCESSFUL_VAL) {
1243 DEBUG ((EFI_D_VERBOSE, "Slot %s is bootable\n", CurrentSlot.Suffix));
1244 return TRUE;
1245 }
1246
1247 DEBUG ((EFI_D_VERBOSE, "Slot %s is unbootable \n", CurrentSlot.Suffix));
1248 return FALSE;
1249}
1250
1251BOOLEAN
1252IsSuffixEmpty (Slot *CheckSlot)
1253{
1254 if (CheckSlot == NULL) {
1255 return TRUE;
1256 }
1257
1258 if (StrLen (CheckSlot->Suffix) == 0) {
1259 return TRUE;
1260 }
1261 return FALSE;
1262}
1263
1264STATIC EFI_STATUS
1265GetActiveSlot (Slot *ActiveSlot)
1266{
1267 EFI_STATUS Status = EFI_SUCCESS;
1268 Slot Slots[] = {{L"_a"}, {L"_b"}};
1269 UINT64 Priority = 0;
1270
1271 if (ActiveSlot == NULL) {
1272 DEBUG ((EFI_D_ERROR, "GetActiveSlot: bad parameter\n"));
1273 return EFI_INVALID_PARAMETER;
1274 }
1275
1276 for (UINTN SlotIndex = 0; SlotIndex < ARRAY_SIZE (Slots); SlotIndex++) {
1277 struct PartitionEntry *BootPartition =
1278 GetBootPartitionEntry (&Slots[SlotIndex]);
1279 UINT64 BootPriority = 0;
1280 if (BootPartition == NULL) {
1281 DEBUG ((EFI_D_ERROR, "GetActiveSlot: No boot partition "
1282 "entry for slot %s\n",
1283 Slots[SlotIndex].Suffix));
1284 return EFI_NOT_FOUND;
1285 }
1286
1287 BootPriority =
1288 (BootPartition->PartEntry.Attributes & PART_ATT_PRIORITY_VAL) >>
1289 PART_ATT_PRIORITY_BIT;
1290
1291 if ((BootPartition->PartEntry.Attributes & PART_ATT_ACTIVE_VAL) &&
1292 (BootPriority > Priority)) {
1293 GUARD (StrnCpyS (ActiveSlot->Suffix, ARRAY_SIZE (ActiveSlot->Suffix),
1294 Slots[SlotIndex].Suffix,
1295 StrLen (Slots[SlotIndex].Suffix)));
1296 Priority = BootPriority;
1297 }
1298 }
1299
1300 DEBUG ((EFI_D_VERBOSE, "GetActiveSlot: found active slot %s, priority %d\n",
1301 ActiveSlot->Suffix, Priority));
1302
1303 if (IsSuffixEmpty (ActiveSlot) == TRUE) {
1304 /* Check for first boot and set default slot */
1305 /* For First boot all A/B attributes for the slot would be 0 */
1306 UINT64 BootPriority = 0;
1307 UINT64 RetryCount = 0;
1308 struct PartitionEntry *SlotA = GetBootPartitionEntry (&Slots[0]);
1309 if (SlotA == NULL) {
1310 DEBUG ((EFI_D_ERROR, "GetActiveSlot: First Boot: No boot partition "
1311 "entry for slot %s\n",
1312 Slots[0].Suffix));
1313 return EFI_NOT_FOUND;
1314 }
1315
1316 BootPriority = (SlotA->PartEntry.Attributes & PART_ATT_PRIORITY_VAL) >>
1317 PART_ATT_PRIORITY_BIT;
1318 RetryCount = (SlotA->PartEntry.Attributes & PART_ATT_MAX_RETRY_COUNT_VAL) >>
1319 PART_ATT_MAX_RETRY_CNT_BIT;
1320
1321 if ((SlotA->PartEntry.Attributes & PART_ATT_ACTIVE_VAL) == 0 &&
1322 (SlotA->PartEntry.Attributes & PART_ATT_SUCCESSFUL_VAL) == 0 &&
1323 (SlotA->PartEntry.Attributes & PART_ATT_UNBOOTABLE_VAL) == 0 &&
1324 BootPriority == 0) {
1325
1326 DEBUG ((EFI_D_INFO, "GetActiveSlot: First boot: set "
1327 "default slot _a\n"));
1328 SlotA->PartEntry.Attributes &=
1329 (~PART_ATT_SUCCESSFUL_VAL & ~PART_ATT_UNBOOTABLE_VAL);
1330 SlotA->PartEntry.Attributes |=
1331 (PART_ATT_PRIORITY_VAL | PART_ATT_ACTIVE_VAL |
1332 PART_ATT_MAX_RETRY_COUNT_VAL);
1333
1334 GUARD (StrnCpyS (ActiveSlot->Suffix, ARRAY_SIZE (ActiveSlot->Suffix),
1335 Slots[0].Suffix, StrLen (Slots[0].Suffix)));
lijuang5b762962019-03-15 20:40:45 +08001336 UpdatePartitionAttributes (PARTITION_ATTRIBUTES);
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001337 FirstBoot = TRUE;
1338 return EFI_SUCCESS;
1339 }
1340
1341 DEBUG ((EFI_D_ERROR, "GetActiveSlot: No active slot found\n"));
1342 DEBUG ((EFI_D_ERROR, "GetActiveSlot: Slot attr: Priority %ld, Retry "
1343 "%ld, Active %ld, Success %ld, unboot %ld\n",
1344 BootPriority, RetryCount,
1345 (SlotA->PartEntry.Attributes & PART_ATT_ACTIVE_VAL) >>
1346 PART_ATT_ACTIVE_BIT,
1347 (SlotA->PartEntry.Attributes & PART_ATT_SUCCESSFUL_VAL),
1348 (SlotA->PartEntry.Attributes & PART_ATT_UNBOOTABLE_VAL)));
1349
1350 return EFI_NOT_FOUND;
1351 }
1352
1353 return EFI_SUCCESS;
1354}
1355
1356EFI_STATUS
Jeevan Shriram39c9b7e2018-09-21 12:21:22 -07001357SetActiveSlot (Slot *NewSlot, BOOLEAN ResetSuccessBit)
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001358{
1359 EFI_STATUS Status = EFI_SUCCESS;
1360 Slot CurrentSlot = {{0}};
1361 Slot *AlternateSlot = NULL;
1362 Slot Slots[] = {{L"_a"}, {L"_b"}};
Jeevan Shriramb1cbe922017-12-11 19:14:18 -08001363 BOOLEAN UfsGet = TRUE;
1364 BOOLEAN UfsSet = FALSE;
1365 UINT32 UfsBootLun = 0;
1366 CHAR8 BootDeviceType[BOOT_DEV_NAME_SIZE_MAX];
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001367 struct PartitionEntry *BootEntry = NULL;
1368
1369 if (NewSlot == NULL) {
1370 DEBUG ((EFI_D_ERROR, "SetActiveSlot: input parameter invalid\n"));
1371 return EFI_INVALID_PARAMETER;
1372 }
1373
1374 GUARD (GetActiveSlot (&CurrentSlot));
1375
1376 if (StrnCmp (NewSlot->Suffix, Slots[0].Suffix, StrLen (Slots[0].Suffix)) ==
1377 0) {
1378 AlternateSlot = &Slots[1];
1379 } else {
1380 AlternateSlot = &Slots[0];
1381 }
1382
1383 BootEntry = GetBootPartitionEntry (NewSlot);
1384 if (BootEntry == NULL) {
1385 DEBUG ((EFI_D_ERROR, "SetActiveSlot: No boot partition entry for slot %s\n",
1386 NewSlot->Suffix));
1387 return EFI_NOT_FOUND;
1388 }
1389
1390 BootEntry->PartEntry.Attributes |=
1391 (PART_ATT_PRIORITY_VAL | PART_ATT_ACTIVE_VAL |
1392 PART_ATT_MAX_RETRY_COUNT_VAL);
Jeevan Shriram39c9b7e2018-09-21 12:21:22 -07001393
1394 BootEntry->PartEntry.Attributes &= (~PART_ATT_UNBOOTABLE_VAL);
1395
1396 if (ResetSuccessBit &&
1397 (BootEntry->PartEntry.Attributes & PART_ATT_SUCCESSFUL_VAL)) {
1398 BootEntry->PartEntry.Attributes &= (~PART_ATT_SUCCESSFUL_VAL);
1399 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001400
1401 /* Reduce the priority and clear the active flag for alternate slot*/
1402 BootEntry = GetBootPartitionEntry (AlternateSlot);
1403 if (BootEntry == NULL) {
1404 DEBUG ((EFI_D_ERROR, "SetActiveSlot: No boot partition entry for slot %s\n",
1405 AlternateSlot->Suffix));
1406 return EFI_NOT_FOUND;
1407 }
1408
1409 BootEntry->PartEntry.Attributes &=
1410 (~PART_ATT_PRIORITY_VAL & ~PART_ATT_ACTIVE_VAL);
1411 BootEntry->PartEntry.Attributes |=
1412 (((UINT64)MAX_PRIORITY - 1) << PART_ATT_PRIORITY_BIT);
1413
lijuang5b762962019-03-15 20:40:45 +08001414 UpdatePartitionAttributes (PARTITION_ATTRIBUTES);
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001415 if (StrnCmp (CurrentSlot.Suffix, NewSlot->Suffix,
1416 StrLen (CurrentSlot.Suffix)) == 0) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001417 DEBUG ((EFI_D_INFO, "SetActiveSlot: %s already active slot\n",
1418 NewSlot->Suffix));
Jeevan Shriramb1cbe922017-12-11 19:14:18 -08001419
1420 /* Check if BootLun is matching with Slot */
1421 GetRootDeviceType (BootDeviceType, BOOT_DEV_NAME_SIZE_MAX);
1422 if (!AsciiStrnCmp (BootDeviceType, "UFS", AsciiStrLen ("UFS"))) {
1423 UfsGetSetBootLun (&UfsBootLun, UfsGet);
1424 if (UfsBootLun == 0x1 &&
1425 !StrnCmp (CurrentSlot.Suffix, (CONST CHAR16 *)L"_b",
1426 StrLen ((CONST CHAR16 *)L"_b"))) {
1427 DEBUG ((EFI_D_INFO, "Boot lun mismatch switch from 1 to 2\n"));
1428 DEBUG ((EFI_D_INFO, "Reboot Required\n"));
1429 UfsBootLun = 0x2;
1430 UfsGetSetBootLun (&UfsBootLun, UfsSet);
1431 } else if (UfsBootLun == 0x2 &&
1432 !StrnCmp (CurrentSlot.Suffix, (CONST CHAR16 *)L"_a",
1433 StrLen ((CONST CHAR16 *)L"_a"))) {
1434 DEBUG ((EFI_D_INFO, "Boot lun mismatch switch from 2 to 1\n"));
1435 DEBUG ((EFI_D_INFO, "Reboot Required\n"));
1436 UfsBootLun = 0x1;
1437 UfsGetSetBootLun (&UfsBootLun, UfsSet);
1438 }
1439 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001440 } else {
1441 DEBUG ((EFI_D_INFO, "Alternate slot %s, New slot %s\n",
1442 AlternateSlot->Suffix, NewSlot->Suffix));
1443 SwitchPtnSlots (NewSlot->Suffix);
1444 MarkPtnActive (NewSlot->Suffix);
1445 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001446 return EFI_SUCCESS;
1447}
1448
1449EFI_STATUS HandleActiveSlotUnbootable (VOID)
1450{
1451 EFI_STATUS Status = EFI_SUCCESS;
1452 struct PartitionEntry *BootEntry = NULL;
1453 Slot ActiveSlot = {{0}};
1454 Slot *AlternateSlot = NULL;
1455 Slot Slots[] = {{L"_a"}, {L"_b"}};
1456 UINT64 Unbootable = 0;
1457 UINT64 BootSuccess = 0;
1458
1459 /* Mark current Slot as unbootable */
1460 GUARD (GetActiveSlot (&ActiveSlot));
1461 BootEntry = GetBootPartitionEntry (&ActiveSlot);
1462 if (BootEntry == NULL) {
1463 DEBUG ((EFI_D_ERROR, "HandleActiveSlotUnbootable: No boot "
1464 "partition entry for slot %s\n",
1465 ActiveSlot.Suffix));
1466 return EFI_NOT_FOUND;
1467 }
1468
1469 if (FirstBoot && !TargetBuildVariantUser ()) {
1470 DEBUG ((EFI_D_VERBOSE, "FirstBoot, skipping slot Unbootable\n"));
1471 FirstBoot = FALSE;
1472 } else {
1473 BootEntry->PartEntry.Attributes |=
1474 (PART_ATT_UNBOOTABLE_VAL) & (~PART_ATT_SUCCESSFUL_VAL);
lijuang5b762962019-03-15 20:40:45 +08001475 UpdatePartitionAttributes (PARTITION_ATTRIBUTES);
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001476 }
1477
1478 if (StrnCmp (ActiveSlot.Suffix, Slots[0].Suffix, StrLen (Slots[0].Suffix)) ==
1479 0) {
1480 AlternateSlot = &Slots[1];
1481 } else {
1482 AlternateSlot = &Slots[0];
1483 }
1484
1485 /* Validate Aternate Slot is bootable */
1486 BootEntry = GetBootPartitionEntry (AlternateSlot);
1487 if (BootEntry == NULL) {
1488 DEBUG ((EFI_D_ERROR, "HandleActiveSlotUnbootable: No boot "
1489 "partition entry for slot %s\n",
1490 AlternateSlot->Suffix));
1491 return EFI_NOT_FOUND;
1492 }
1493
1494 Unbootable = (BootEntry->PartEntry.Attributes & PART_ATT_UNBOOTABLE_VAL) >>
1495 PART_ATT_UNBOOTABLE_BIT;
1496 BootSuccess = (BootEntry->PartEntry.Attributes & PART_ATT_SUCCESSFUL_VAL) >>
1497 PART_ATT_SUCCESS_BIT;
1498
1499 if (Unbootable == 0 && BootSuccess == 1) {
1500 DEBUG (
1501 (EFI_D_INFO, "Alternate Slot %s is bootable\n", AlternateSlot->Suffix));
Jeevan Shriram39c9b7e2018-09-21 12:21:22 -07001502 GUARD (SetActiveSlot (AlternateSlot, FALSE));
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001503
1504 DEBUG ((EFI_D_INFO, "HandleActiveSlotUnbootable: Rebooting\n"));
1505 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
1506
1507 // Shouldn't get here
1508 DEBUG ((EFI_D_ERROR, "HandleActiveSlotUnbootable: "
1509 "gRT->Resetystem didn't work\n"));
1510 return EFI_LOAD_ERROR;
1511 }
1512
1513 return EFI_LOAD_ERROR;
1514}
1515
1516EFI_STATUS ClearUnbootable (VOID)
1517{
1518 EFI_STATUS Status = EFI_SUCCESS;
1519 Slot ActiveSlot = {{0}};
1520 struct PartitionEntry *BootEntry = NULL;
1521
1522 Status = GetActiveSlot (&ActiveSlot);
1523 if (Status != EFI_SUCCESS) {
1524 DEBUG ((EFI_D_ERROR, "ClearUnbootable: GetActiveSlot failed.\n"));
1525 return Status;
1526 }
1527 BootEntry = GetBootPartitionEntry (&ActiveSlot);
1528 if (BootEntry == NULL) {
1529 DEBUG ((EFI_D_ERROR,
1530 "ClearUnbootable: No boot partition entry for slot %s\n",
1531 ActiveSlot.Suffix));
1532 return EFI_NOT_FOUND;
1533 }
1534 BootEntry->PartEntry.Attributes &= ~PART_ATT_UNBOOTABLE_VAL;
lijuang5b762962019-03-15 20:40:45 +08001535 UpdatePartitionAttributes (PARTITION_ATTRIBUTES);
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001536 return EFI_SUCCESS;
1537}
1538
1539STATIC EFI_STATUS
1540ValidateSlotGuids (Slot *BootableSlot)
1541{
1542 EFI_STATUS Status = EFI_SUCCESS;
1543 struct PartitionEntry *BootEntry = NULL;
Mayank Groverf70d1a82019-02-26 17:52:19 +05301544 CHAR16 PartitionName[] = L"abl_x";
1545 CONST struct PartitionEntry *PartEntry = NULL;
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001546 CHAR8 BootDeviceType[BOOT_DEV_NAME_SIZE_MAX];
1547 UINT32 UfsBootLun = 0;
1548
1549 BootEntry = GetBootPartitionEntry (BootableSlot);
1550 if (BootEntry == NULL) {
1551 DEBUG ((EFI_D_ERROR, "ValidateSlotGuids: No boot partition "
1552 "entry for slot %s\n",
1553 BootableSlot->Suffix));
1554 return EFI_NOT_FOUND;
1555 }
1556
Mayank Groverf70d1a82019-02-26 17:52:19 +05301557 PartitionName[StrLen (PartitionName) - 1] =
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001558 BootableSlot->Suffix[StrLen (BootableSlot->Suffix) - 1];
Mayank Groverf70d1a82019-02-26 17:52:19 +05301559 PartEntry = GetPartitionEntry (PartitionName);
1560 if (PartEntry == NULL) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001561 DEBUG ((EFI_D_ERROR, "ValidateSlotGuids: No partition entry for %s\n",
Mayank Groverf70d1a82019-02-26 17:52:19 +05301562 PartitionName));
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001563 return EFI_NOT_FOUND;
1564 }
1565
1566 if (CompareMem (&BootEntry->PartEntry.PartitionTypeGUID,
Mayank Groverf70d1a82019-02-26 17:52:19 +05301567 &PartEntry->PartEntry.PartitionTypeGUID,
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001568 sizeof (EFI_GUID)) == 0) {
1569 DEBUG ((EFI_D_ERROR, "ValidateSlotGuids: BootableSlot %s does "
1570 "not have valid guids\n",
1571 BootableSlot->Suffix));
1572 DEBUG ((EFI_D_INFO, "Boot GUID %g\n",
1573 &BootEntry->PartEntry.PartitionTypeGUID));
Mayank Groverf70d1a82019-02-26 17:52:19 +05301574 DEBUG ((EFI_D_INFO, "%s GUID %g\n",
1575 PartitionName, &PartEntry->PartEntry.PartitionTypeGUID));
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001576 return EFI_DEVICE_ERROR;
1577 }
1578
1579 GetRootDeviceType (BootDeviceType, BOOT_DEV_NAME_SIZE_MAX);
1580 if (!AsciiStrnCmp (BootDeviceType, "UFS", AsciiStrLen ("UFS"))) {
1581 GUARD (UfsGetSetBootLun (&UfsBootLun, TRUE));
1582 if (UfsBootLun == 0x1 &&
1583 !StrCmp (BootableSlot->Suffix, (CONST CHAR16 *)L"_a")) {
1584 } else if (UfsBootLun == 0x2 &&
1585 !StrCmp (BootableSlot->Suffix, (CONST CHAR16 *)L"_b")) {
1586 } else {
1587 DEBUG ((EFI_D_ERROR, "Boot lun: %x and BootableSlot: %s "
1588 "do not match\n",
1589 UfsBootLun, BootableSlot->Suffix));
1590 return EFI_DEVICE_ERROR;
1591 }
1592 } else if (!AsciiStrnCmp (BootDeviceType, "EMMC", AsciiStrLen ("EMMC"))) {
1593 } else {
1594 DEBUG ((EFI_D_ERROR, "Unsupported Device Type\n"));
1595 return EFI_DEVICE_ERROR;
1596 }
1597
1598 DEBUG ((EFI_D_INFO, "Booting from slot (%s)\n", BootableSlot->Suffix));
1599 return EFI_SUCCESS;
1600}
1601
1602EFI_STATUS
1603FindBootableSlot (Slot *BootableSlot)
1604{
1605 EFI_STATUS Status = EFI_SUCCESS;
1606 struct PartitionEntry *BootEntry = NULL;
1607 UINT64 Unbootable = 0;
1608 UINT64 BootSuccess = 0;
1609 UINT64 RetryCount = 0;
1610
1611 if (BootableSlot == NULL) {
1612 DEBUG ((EFI_D_ERROR, "FindBootableSlot: input parameter invalid\n"));
1613 return EFI_INVALID_PARAMETER;
1614 }
1615
jianzhou71e1ea62017-12-01 16:27:17 +08001616 GUARD (GetActiveSlot (BootableSlot));
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001617
1618 /* Validate Active Slot is bootable */
1619 BootEntry = GetBootPartitionEntry (BootableSlot);
1620 if (BootEntry == NULL) {
1621 DEBUG ((EFI_D_ERROR, "FindBootableSlot: No boot partition entry "
1622 "for slot %s\n",
1623 BootableSlot->Suffix));
1624 return EFI_NOT_FOUND;
1625 }
1626
1627 Unbootable = (BootEntry->PartEntry.Attributes & PART_ATT_UNBOOTABLE_VAL) >>
1628 PART_ATT_UNBOOTABLE_BIT;
1629 BootSuccess = (BootEntry->PartEntry.Attributes & PART_ATT_SUCCESSFUL_VAL) >>
1630 PART_ATT_SUCCESS_BIT;
1631 RetryCount =
1632 (BootEntry->PartEntry.Attributes & PART_ATT_MAX_RETRY_COUNT_VAL) >>
1633 PART_ATT_MAX_RETRY_CNT_BIT;
1634
1635 if (Unbootable == 0 && BootSuccess == 1) {
1636 DEBUG (
1637 (EFI_D_VERBOSE, "Active Slot %s is bootable\n", BootableSlot->Suffix));
1638 } else if (Unbootable == 0 && BootSuccess == 0 && RetryCount > 0) {
lijuangb53e91c2019-08-14 18:22:20 +08001639 if ((!IsABRetryCountDisabled () &&
1640 !IsBootDevImage ()) &&
1641 IsABRetryCountUpdateRequired ()) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001642 RetryCount--;
1643 BootEntry->PartEntry.Attributes &= ~PART_ATT_MAX_RETRY_COUNT_VAL;
1644 BootEntry->PartEntry.Attributes |= RetryCount
1645 << PART_ATT_MAX_RETRY_CNT_BIT;
lijuang5b762962019-03-15 20:40:45 +08001646 UpdatePartitionAttributes (PARTITION_ATTRIBUTES);
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001647 DEBUG ((EFI_D_INFO, "Active Slot %s is bootable, retry count %ld\n",
1648 BootableSlot->Suffix, RetryCount));
Jeevan Shriram0a3ba0b2019-01-02 23:21:12 -08001649 } else {
1650 DEBUG ((EFI_D_INFO, "A/B retry count NOT decremented\n"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001651 }
1652 } else {
1653 DEBUG ((EFI_D_INFO, "Slot %s is unbootable, trying alternate slot\n",
1654 BootableSlot->Suffix));
1655 GUARD_OUT (HandleActiveSlotUnbootable ());
1656 }
1657
1658 /* Validate slot suffix and partition guids */
Nagireddy Annem672b53f2019-11-11 13:55:48 +05301659 if (Status == EFI_SUCCESS &&
1660 NAND != CheckRootDeviceType ()) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001661 GUARD_OUT (ValidateSlotGuids (BootableSlot));
1662 }
1663 MarkPtnActive (BootableSlot->Suffix);
Shivaprasad Hongalc017e812017-04-26 16:15:27 -07001664out:
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001665 if (Status != EFI_SUCCESS) {
1666 /* clear bootable slot */
1667 BootableSlot->Suffix[0] = '\0';
1668 }
1669 return Status;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301670}
1671
lijuang3df1faf2018-04-10 21:59:25 +08001672/* This functions should be called only if header revision > 0 */
1673STATIC EFI_STATUS GetRecoveryDtboInfo (BootInfo *Info,
1674 BootParamlist *BootParamlistPtr,
1675 UINT64 *DtboImageSize)
1676{
1677 UINT32 HeaderVersion = 0;
1678 UINT64 RecoveryDtboOffset = 0;
1679 UINT32 RecoveryDtboSize = 0;
1680 UINT32 ImageHeaderSize = 0;
1681 struct boot_img_hdr_v1 *BootImgHdrV1Addr;
1682
1683 if (Info == NULL ||
1684 BootParamlistPtr == NULL ||
1685 DtboImageSize == NULL) {
1686 DEBUG ((EFI_D_ERROR, "Invalid input parameters\n"));
1687 return EFI_INVALID_PARAMETER;
1688 }
1689
1690 HeaderVersion = Info->HeaderVersion;
1691
1692 /* Finds out the location of recovery dtbo size and offset */
1693 BootImgHdrV1Addr = (struct boot_img_hdr_v1 *)
1694 ((UINT64) BootParamlistPtr->ImageBuffer +
1695 BOOT_IMAGE_HEADER_V1_RECOVERY_DTBO_SIZE_OFFSET);
1696
1697 if (HeaderVersion == BOOT_HEADER_VERSION_ONE) {
1698 ImageHeaderSize = BootImgHdrV1Addr->header_size;
1699
1700 if ((ImageHeaderSize != (sizeof (struct boot_img_hdr_v1) +
1701 BOOT_IMAGE_HEADER_V1_RECOVERY_DTBO_SIZE_OFFSET)) ||
1702 ImageHeaderSize > BootParamlistPtr->PageSize) {
1703 DEBUG ((EFI_D_ERROR,
1704 "Invalid boot image header: %d\n", ImageHeaderSize));
1705 return EFI_BAD_BUFFER_SIZE;
1706 }
1707 }
1708
1709 RecoveryDtboOffset = BootImgHdrV1Addr->recovery_dtbo_offset;
1710 RecoveryDtboSize = ROUND_TO_PAGE (BootImgHdrV1Addr->recovery_dtbo_size,
1711 BootParamlistPtr->PageSize - 1);
1712
1713 if (CHECK_ADD64 (RecoveryDtboOffset, RecoveryDtboSize)) {
Mukesh Ojha82911f82018-04-30 16:45:07 +05301714 DEBUG ((EFI_D_ERROR, "Integer Overflow: RecoveryDtboOffset=%u "
lijuang3df1faf2018-04-10 21:59:25 +08001715 "RecoveryDtboSize=%u\n", RecoveryDtboOffset, RecoveryDtboSize));
1716 return EFI_BAD_BUFFER_SIZE;
1717 }
1718
1719 if (RecoveryDtboOffset + RecoveryDtboSize >
1720 BootParamlistPtr->ImageSize) {
1721 DEBUG ((EFI_D_ERROR, "Invalid recovery dtbo: RecoveryDtboOffset=%u,"
1722 " RecoveryDtboSize=%u, ImageSize=%u\n",
1723 RecoveryDtboOffset, RecoveryDtboSize,
1724 BootParamlistPtr->ImageSize));
1725 return EFI_BAD_BUFFER_SIZE;
1726 }
1727
1728 BootParamlistPtr->DtboImgBuffer = (VOID *)
1729 ((UINT64) BootParamlistPtr->ImageBuffer +
1730 RecoveryDtboOffset);
1731
1732 *DtboImageSize = RecoveryDtboSize;
1733
1734 DEBUG ((EFI_D_VERBOSE, "Image Header Version: 0x%x\n", HeaderVersion));
1735 DEBUG ((EFI_D_VERBOSE, "Recovery Dtbo Offset: 0x%x\n",
1736 RecoveryDtboOffset));
1737 DEBUG ((EFI_D_VERBOSE, "Recovery Dtbo Size: 0x%x\n", *DtboImageSize));
1738
1739 return EFI_SUCCESS;
1740}
1741
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301742/*Function to provide Dtbo Present info
1743 *return: TRUE or FALSE.
1744 */
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001745BOOLEAN
lijuang3df1faf2018-04-10 21:59:25 +08001746LoadAndValidateDtboImg (BootInfo *Info,
1747 BootParamlist *BootParamlistPtr)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301748{
lijuang3df1faf2018-04-10 21:59:25 +08001749 UINT64 DtboImgSize = 0;
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001750 EFI_STATUS Status = EFI_SUCCESS;
1751 struct DtboTableHdr *DtboTableHdr = NULL;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301752
Mayank Groverf70d1a82019-02-26 17:52:19 +05301753 if ((!Info->MultiSlotBoot ||
1754 IsDynamicPartitionSupport ()) &&
lijuang3df1faf2018-04-10 21:59:25 +08001755 Info->BootIntoRecovery &&
Raghavendra Rao Ananta07469562019-10-11 08:53:20 -07001756 Info->HeaderVersion > BOOT_HEADER_VERSION_ZERO &&
1757 Info->HeaderVersion < BOOT_HEADER_VERSION_THREE) {
lijuang3df1faf2018-04-10 21:59:25 +08001758 Status = GetRecoveryDtboInfo (Info, BootParamlistPtr, &DtboImgSize);
1759 } else {
1760 Status = GetImage (Info, &BootParamlistPtr->DtboImgBuffer,
1761 (UINTN *)&DtboImgSize, "dtbo");
1762 }
1763
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001764 if (Status != EFI_SUCCESS) {
lijuang3df1faf2018-04-10 21:59:25 +08001765 DEBUG ((EFI_D_ERROR, "BootLinux: failed to get dtbo image\n"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001766 return FALSE;
1767 }
lijuang3df1faf2018-04-10 21:59:25 +08001768
1769 if (!BootParamlistPtr->DtboImgBuffer) {
lijuangc336a292017-08-22 19:48:49 +08001770 DEBUG ((EFI_D_ERROR, "DtboImgBuffer is NULL"));
1771 return FALSE;
1772 }
Vijay Kumar Pendoti6fc41c42017-05-09 19:41:26 +05301773
lijuang3df1faf2018-04-10 21:59:25 +08001774 DtboTableHdr = BootParamlistPtr->DtboImgBuffer;
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001775 if (fdt32_to_cpu (DtboTableHdr->Magic) != DTBO_TABLE_MAGIC) {
1776 DEBUG ((EFI_D_ERROR, "Dtbo hdr magic mismatch %x, with %x\n",
1777 DtboTableHdr->Magic, DTBO_TABLE_MAGIC));
1778 return FALSE;
1779 }
Vijay Kumar Pendoti6fc41c42017-05-09 19:41:26 +05301780
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001781 if (DtboImgSize > DTBO_MAX_SIZE_ALLOWED) {
1782 DEBUG ((EFI_D_ERROR, "Dtbo Size too big %x, Allowed size %x\n", DtboImgSize,
1783 DTBO_MAX_SIZE_ALLOWED));
1784 return FALSE;
1785 }
Vijay Kumar Pendoti6fc41c42017-05-09 19:41:26 +05301786
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001787 /*Check for TotalSize of Dtbo image*/
1788 if ((fdt32_to_cpu (DtboTableHdr->TotalSize) > DTBO_MAX_SIZE_ALLOWED) ||
1789 (fdt32_to_cpu (DtboTableHdr->TotalSize) == 0)) {
1790 DEBUG ((EFI_D_ERROR, "Dtbo Table TotalSize got corrupted\n"));
1791 return FALSE;
1792 }
Vijay Kumar Pendoti6fc41c42017-05-09 19:41:26 +05301793
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001794 /*Check for HeaderSize of Dtbo image*/
1795 if (fdt32_to_cpu (DtboTableHdr->HeaderSize) != sizeof (struct DtboTableHdr)) {
1796 DEBUG ((EFI_D_ERROR, "Dtbo Table HeaderSize got corrupted\n"));
1797 return FALSE;
1798 }
Vijay Kumar Pendoti6fc41c42017-05-09 19:41:26 +05301799
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001800 /*Check for DtEntrySize of Dtbo image*/
1801 if (fdt32_to_cpu (DtboTableHdr->DtEntrySize) !=
1802 sizeof (struct DtboTableEntry)) {
1803 DEBUG ((EFI_D_ERROR, "Dtbo Table DtEntrySize got corrupted\n"));
1804 return FALSE;
1805 }
Vijay Kumar Pendoti6fc41c42017-05-09 19:41:26 +05301806
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001807 /*Check for DtEntryOffset of Dtbo image*/
1808 if (fdt32_to_cpu (DtboTableHdr->DtEntryOffset) > DTBO_MAX_SIZE_ALLOWED) {
1809 DEBUG ((EFI_D_ERROR, "Dtbo Table DtEntryOffset got corrupted\n"));
1810 return FALSE;
1811 }
Vijay Kumar Pendoti6fc41c42017-05-09 19:41:26 +05301812
jianzhou32412192017-11-10 14:22:47 +08001813 if ((UINT64)fdt32_to_cpu (DtboTableHdr->DtEntryCount) *
1814 fdt32_to_cpu (DtboTableHdr->DtEntrySize) > DtboImgSize) {
1815 DEBUG ((EFI_D_ERROR,
1816 "DTB header is corrupted, DtEntryCount %x, DtEntrySize %x,"
1817 " DtboImgSize %x\n", fdt32_to_cpu (DtboTableHdr->DtEntryCount),
1818 fdt32_to_cpu (DtboTableHdr->DtEntrySize), DtboImgSize));
1819 return FALSE;
1820 }
1821
1822 if (fdt32_to_cpu (DtboTableHdr->DtEntryOffset) +
1823 (UINT64)fdt32_to_cpu (DtboTableHdr->DtEntryCount) *
1824 fdt32_to_cpu (DtboTableHdr->DtEntrySize) > DtboImgSize) {
1825 DEBUG ((EFI_D_ERROR,
1826 "DTB header is corrupted, DtEntryOffset %x, DtEntryCount %x,"
1827 "DtEntrySize %x, DtboImgSize %x\n",
1828 fdt32_to_cpu (DtboTableHdr->DtEntryOffset),
1829 fdt32_to_cpu (DtboTableHdr->DtEntryCount),
1830 fdt32_to_cpu (DtboTableHdr->DtEntrySize), DtboImgSize));
1831 return FALSE;
1832 }
1833
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001834 return TRUE;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301835}
Nagireddy Annem672b53f2019-11-11 13:55:48 +05301836
1837EFI_STATUS NandABUpdatePartition (UINT32 UpdateType)
1838{
1839 Slot Slots[] = {{L"_a"}, {L"_b"}};
1840 NandABAttr *NandAttr = NULL;
1841 EFI_GUID Ptype = gEfiMiscPartitionGuid;
1842 EFI_STATUS Status;
1843 UINT32 PageSize;
1844 size_t Size1 = sizeof (PtnEntries[0].PartEntry.PartitionName);
1845 size_t Size2 = sizeof (NandAttr->Slots[0].SlotName);
1846
1847 GetPageSize (&PageSize);
1848 Status = GetNandMiscPartiGuid (&Ptype);
1849 if (Status != EFI_SUCCESS) {
1850 return Status;
1851 }
1852
1853 Status = ReadFromPartition (&Ptype, (VOID **)&NandAttr, PageSize);
1854 if (Status != EFI_SUCCESS) {
1855 DEBUG ((EFI_D_ERROR, "Error Reading from misc partition: %r\n", Status));
1856 return Status;
1857 }
1858
1859 if (!NandAttr) {
1860 DEBUG ((EFI_D_ERROR, "Error in loading Data from misc partition\n"));
1861 return EFI_INVALID_PARAMETER;
1862 }
1863
1864 for (UINTN SlotIndex = 0; SlotIndex < ARRAY_SIZE (Slots); SlotIndex++) {
1865 struct PartitionEntry *BootPartition =
1866 GetBootPartitionEntry (&Slots[SlotIndex]);
1867 if (BootPartition == NULL) {
1868 DEBUG ((EFI_D_ERROR, "GetActiveSlot: No boot partition "
1869 "entry for slot %s\n", Slots[SlotIndex].Suffix));
1870 Status = EFI_NOT_FOUND;
1871 goto Exit;
1872 }
1873
1874 if (UpdateType == PTN_ENTRIES_TO_MISC) {
1875 NandAttr->Slots[SlotIndex].Attributes =
1876 (CHAR8)((BootPartition->PartEntry.Attributes >>
1877 PART_ATT_PRIORITY_BIT)&0xff);
1878 StrnCpyS (NandAttr->Slots[SlotIndex].SlotName, Size2 ,
1879 (BootPartition->PartEntry.PartitionName), Size1);
1880 } else if (!StrnCmp (BootPartition->PartEntry.PartitionName,
1881 NandAttr->Slots[SlotIndex].SlotName, Size2)) {
1882 BootPartition->PartEntry.Attributes =
1883 (((UINT64)((NandAttr->Slots[SlotIndex].Attributes)&0xff)) <<
1884 PART_ATT_PRIORITY_BIT);
1885 }
1886 }
1887
1888 if (UpdateType == PTN_ENTRIES_TO_MISC) {
1889 WriteToPartition (&Ptype, NandAttr, sizeof (struct NandABAttr));
1890 }
1891
1892Exit:
1893 if (NandAttr) {
1894 FreePool (NandAttr);
1895 NandAttr = NULL;
1896 }
1897
1898 return Status;
1899}