]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPlatformPkg/FileSystem/BootMonFs/BootMonFsImages.c
ArmPlatformPkg/BootMonFs: Added support for new revision of the NOR Flash file system
[mirror_edk2.git] / ArmPlatformPkg / FileSystem / BootMonFs / BootMonFsImages.c
1 /** @file
2 *
3 * Copyright (c) 2012-2014, ARM Limited. All rights reserved.
4 *
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
9 *
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 *
13 **/
14
15 #include <Library/IoLib.h>
16 #include <Library/NorFlashPlatformLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/MemoryAllocationLib.h>
19
20 #include <Protocol/SimpleFileSystem.h>
21
22 #include "BootMonFsInternal.h"
23
24 UINT32
25 BootMonFsChecksum (
26 IN VOID *Data,
27 IN UINT32 Size
28 )
29 {
30 UINT32 *Ptr;
31 UINT32 Word;
32 UINT32 Checksum;
33
34 ASSERT (Size % 4 == 0);
35
36 Checksum = 0;
37 Ptr = (UINT32*)Data;
38
39 while (Size > 0) {
40 Word = *Ptr++;
41 Size -= 4;
42
43 if (Word > ~Checksum) {
44 Checksum++;
45 }
46
47 Checksum += Word;
48 }
49
50 return ~Checksum;
51 }
52
53 EFI_STATUS
54 BootMonFsComputeFooterChecksum (
55 IN OUT HW_IMAGE_DESCRIPTION *Footer
56 )
57 {
58 HW_IMAGE_DESCRIPTION *Description;
59 UINT32 Index;
60
61 Footer->Attributes = 1;
62
63 Description = AllocateZeroPool (sizeof (HW_IMAGE_DESCRIPTION));
64 if (Description == NULL) {
65 DEBUG ((DEBUG_ERROR, "BootMonFsComputeFooterChecksum: Unable to allocate memory.\n"));
66 return EFI_OUT_OF_RESOURCES;
67 }
68
69 // Copy over to temporary shim
70 CopyMem (Description, Footer, sizeof (HW_IMAGE_DESCRIPTION));
71
72 // BootMon doesn't checksum the previous checksum
73 Description->FooterChecksum = 0;
74
75 // Blank out regions which aren't being used.
76 for (Index = Footer->RegionCount; Index < HW_IMAGE_DESCRIPTION_REGION_MAX; Index++) {
77 Description->Region[Index].Checksum = 0;
78 Description->Region[Index].LoadAddress = 0;
79 Description->Region[Index].Offset = 0;
80 Description->Region[Index].Size = 0;
81 }
82
83 // Compute the checksum
84 Footer->FooterChecksum = BootMonFsChecksum (Description, sizeof (HW_IMAGE_DESCRIPTION));
85
86 FreePool (Description);
87
88 return EFI_SUCCESS;
89 }
90
91 BOOLEAN
92 BootMonFsImageInThisBlock (
93 IN VOID *Buf,
94 IN UINTN Size,
95 IN UINT32 Block,
96 OUT HW_IMAGE_DESCRIPTION *Image
97 )
98 {
99 EFI_STATUS Status;
100 HW_IMAGE_FOOTER *Ptr;
101 HW_IMAGE_DESCRIPTION *Footer;
102 UINT32 Checksum;
103
104 // The footer is stored as the last thing in the block
105 Ptr = (HW_IMAGE_FOOTER *)((UINT8 *)Buf + Size - sizeof (HW_IMAGE_FOOTER));
106
107 // Check that the verification bytes are present
108 if ((Ptr->FooterSignature1 != HW_IMAGE_FOOTER_SIGNATURE_1) || (Ptr->FooterSignature2 != HW_IMAGE_FOOTER_SIGNATURE_2)) {
109 return FALSE;
110 }
111
112 if (Ptr->Version == HW_IMAGE_FOOTER_VERSION) {
113 if (Ptr->Offset != HW_IMAGE_FOOTER_OFFSET) {
114 return FALSE;
115 }
116 } else if (Ptr->Version == HW_IMAGE_FOOTER_VERSION2) {
117 if (Ptr->Offset != HW_IMAGE_FOOTER_OFFSET2) {
118 return FALSE;
119 }
120 } else {
121 return FALSE;
122 }
123
124 Footer = (HW_IMAGE_DESCRIPTION *)(((UINT8 *)Buf + Size - sizeof (HW_IMAGE_DESCRIPTION)));
125 Checksum = Footer->FooterChecksum;
126 Status = BootMonFsComputeFooterChecksum (Footer);
127 if (EFI_ERROR (Status)) {
128 DEBUG ((DEBUG_ERROR, "Warning: failed to compute checksum for image '%a'\n", Footer->Footer.Filename));
129 }
130
131 if (Footer->FooterChecksum != Checksum) {
132 DEBUG ((DEBUG_ERROR, "Warning: image '%a' checksum mismatch.\n", Footer->Footer.Filename));
133 }
134
135 if ((Footer->BlockEnd != Block) || (Footer->BlockStart > Footer->BlockEnd)) {
136 return FALSE;
137 }
138
139 // Copy the image out
140 CopyMem (Image, Footer, sizeof (HW_IMAGE_DESCRIPTION));
141
142 return TRUE;
143 }
144
145 EFI_STATUS
146 BootMonFsDiscoverNextImage (
147 IN BOOTMON_FS_INSTANCE *Instance,
148 IN EFI_LBA *LbaStart,
149 OUT HW_IMAGE_DESCRIPTION *Image
150 )
151 {
152 EFI_BLOCK_IO_PROTOCOL *Blocks;
153 EFI_LBA CurrentLba;
154 VOID *Out;
155
156 Blocks = Instance->BlockIo;
157
158 // Allocate an output buffer
159 Out = AllocatePool (Instance->Media->BlockSize);
160 if (Out == NULL) {
161 return EFI_OUT_OF_RESOURCES;
162 }
163
164 Blocks->Reset (Blocks, FALSE);
165 CurrentLba = *LbaStart;
166
167 // Look for images in the rest of this block
168 while (CurrentLba <= Instance->Media->LastBlock) {
169 // Read in the next block
170 Blocks->ReadBlocks (Blocks, Instance->Media->MediaId, CurrentLba, Instance->Media->BlockSize, Out);
171 // Check for an image in the current block
172 if (BootMonFsImageInThisBlock (Out, Instance->Media->BlockSize, (CurrentLba - Instance->Media->LowestAlignedLba), Image)) {
173 DEBUG ((EFI_D_ERROR, "Found image: %a in block %d.\n", &(Image->Footer.Filename), (UINTN)(CurrentLba - Instance->Media->LowestAlignedLba)));
174 FreePool (Out);
175 *LbaStart = Image->BlockEnd + 1;
176 return EFI_SUCCESS;
177 } else {
178 CurrentLba++;
179 }
180 }
181
182 *LbaStart = CurrentLba;
183 FreePool (Out);
184 return EFI_NOT_FOUND;
185 }
186
187 EFI_STATUS
188 BootMonFsInitialize (
189 IN BOOTMON_FS_INSTANCE *Instance
190 )
191 {
192 EFI_STATUS Status;
193 EFI_LBA Lba;
194 UINT32 ImageCount;
195 BOOTMON_FS_FILE *NewFile;
196
197 ImageCount = 0;
198 Lba = 0;
199
200 while (1) {
201 Status = BootMonFsCreateFile (Instance, &NewFile);
202 if (EFI_ERROR (Status)) {
203 return Status;
204 }
205
206 Status = BootMonFsDiscoverNextImage (Instance, &Lba, &(NewFile->HwDescription));
207 if (EFI_ERROR (Status)) {
208 // Free NewFile allocated by BootMonFsCreateFile ()
209 FreePool (NewFile);
210 break;
211 }
212 InsertTailList (&Instance->RootFile->Link, &NewFile->Link);
213 ImageCount++;
214 }
215
216 Instance->Initialized = TRUE;
217 return EFI_SUCCESS;
218 }