blob: 514121b2a85e098ef1e52f0df1b3fecbb37df6d5 [file] [log] [blame]
Fabio Utzig61fd8882019-09-14 20:00:20 -03001/*
David Brownaac71112020-02-03 16:13:42 -07002 * SPDX-License-Identifier: Apache-2.0
3 *
Fabio Utzig61fd8882019-09-14 20:00:20 -03004 * Copyright (c) 2019 JUUL Labs
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include <stddef.h>
20
21#include "bootutil/bootutil.h"
22#include "bootutil/image.h"
23#include "bootutil_priv.h"
24
25/*
26 * Initialize a TLV iterator.
27 *
28 * @param it An iterator struct
29 * @param hdr image_header of the slot's image
30 * @param fap flash_area of the slot which is storing the image
31 * @param type Type of TLV to look for
32 * @param prot true if TLV has to be stored in the protected area, false otherwise
33 *
Sam Bristowd0ca0ff2019-10-30 20:51:35 +130034 * @returns 0 if the TLV iterator was successfully started
Fabio Utzig61fd8882019-09-14 20:00:20 -030035 * -1 on errors
36 */
37int
38bootutil_tlv_iter_begin(struct image_tlv_iter *it, const struct image_header *hdr,
David Brownd13318a2019-12-04 17:28:40 -070039 const struct flash_area *fap, uint16_t type, bool prot)
Fabio Utzig61fd8882019-09-14 20:00:20 -030040{
41 uint32_t off_;
42 struct image_tlv_info info;
43
44 if (it == NULL || hdr == NULL || fap == NULL) {
45 return -1;
46 }
47
48 off_ = BOOT_TLV_OFF(hdr);
49 if (flash_area_read(fap, off_, &info, sizeof(info))) {
50 return -1;
51 }
52
Fabio Utzige52c08e2019-09-11 19:32:00 -030053 if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
54 if (hdr->ih_protect_tlv_size != info.it_tlv_tot) {
55 return -1;
56 }
57
58 if (flash_area_read(fap, off_ + info.it_tlv_tot, &info, sizeof(info))) {
59 return -1;
60 }
61 } else if (hdr->ih_protect_tlv_size != 0) {
62 return -1;
63 }
64
Fabio Utzig61fd8882019-09-14 20:00:20 -030065 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
66 return -1;
67 }
68
69 it->hdr = hdr;
70 it->fap = fap;
71 it->type = type;
72 it->prot = prot;
Fabio Utzige52c08e2019-09-11 19:32:00 -030073 it->prot_end = off_ + it->hdr->ih_protect_tlv_size;
74 it->tlv_end = off_ + it->hdr->ih_protect_tlv_size + info.it_tlv_tot;
75 // position on first TLV
76 it->tlv_off = off_ + sizeof(info);
Fabio Utzig61fd8882019-09-14 20:00:20 -030077 return 0;
78}
79
80/*
81 * Find next TLV
82 *
83 * @param it The image TLV iterator struct
84 * @param off The offset of the TLV's payload in flash
85 * @param len The length of the TLV's payload
86 * @param type If not NULL returns the type of TLV found
87 *
88 * @returns 0 if a TLV with with matching type was found
89 * 1 if no more TLVs with matching type are available
90 * -1 on errors
91 */
92int
93bootutil_tlv_iter_next(struct image_tlv_iter *it, uint32_t *off, uint16_t *len,
David Brownd13318a2019-12-04 17:28:40 -070094 uint16_t *type)
Fabio Utzig61fd8882019-09-14 20:00:20 -030095{
96 struct image_tlv tlv;
97 int rc;
98
99 if (it == NULL || it->hdr == NULL || it->fap == NULL) {
100 return -1;
101 }
102
103 while (it->tlv_off < it->tlv_end) {
Fabio Utzige52c08e2019-09-11 19:32:00 -0300104 if (it->hdr->ih_protect_tlv_size > 0 && it->tlv_off == it->prot_end) {
105 it->tlv_off += sizeof(struct image_tlv_info);
106 }
107
Fabio Utzig61fd8882019-09-14 20:00:20 -0300108 rc = flash_area_read(it->fap, it->tlv_off, &tlv, sizeof tlv);
109 if (rc) {
110 return -1;
111 }
112
113 /* No more TLVs in the protected area */
Fabio Utzige52c08e2019-09-11 19:32:00 -0300114 if (it->prot && it->tlv_off >= it->prot_end) {
Fabio Utzig61fd8882019-09-14 20:00:20 -0300115 return 1;
116 }
117
118 if (it->type == IMAGE_TLV_ANY || tlv.it_type == it->type) {
119 if (type != NULL) {
120 *type = tlv.it_type;
121 }
122 *off = it->tlv_off + sizeof(tlv);
123 *len = tlv.it_len;
124 it->tlv_off += sizeof(tlv) + tlv.it_len;
125 return 0;
126 }
127
128 it->tlv_off += sizeof(tlv) + tlv.it_len;
129 }
130
131 return 1;
132}