1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <plat/inc/bl.h>
18 #include <stdbool.h>
19 #include <string.h>
20 #include <stdint.h>
21 #include <eeData.h>
22
23 extern uint32_t __eedata_start[], __eedata_end[];
24
25 //STM32F4xx eedata stores data in 4-byte aligned chunks
26
eeFind(uint32_t nameToFind,uint32_t * offset,bool findFirst,uint32_t * szP)27 static void* eeFind(uint32_t nameToFind, uint32_t *offset, bool findFirst, uint32_t *szP)
28 {
29 uint32_t *p = __eedata_start + (offset ? *offset : 0);
30 void *foundData = NULL;
31
32 //find the last incarnation of "name" in flash area
33 while (p < __eedata_end) {
34 uint32_t info = *p++;
35 uint32_t name = info & EE_DATA_NAME_MAX;
36 uint32_t sz = info / (EE_DATA_NAME_MAX + 1);
37 void *data = p;
38
39 //skip over to next data chunk header
40 p += (sz + 3) / 4;
41
42 //check for a match
43 if (nameToFind == name) {
44 *szP = sz;
45 foundData = data;
46
47 if (findFirst)
48 break;
49 }
50
51 //check for ending condition (name == max)
52 if (name == EE_DATA_NAME_MAX)
53 break;
54 }
55
56 if (offset)
57 *offset = p - __eedata_start;
58
59 return foundData;
60 }
61
eeIsValidName(uint32_t name)62 static bool eeIsValidName(uint32_t name)
63 {
64 return name && name < EE_DATA_NAME_MAX;
65 }
66
eeDataGetEx(uint32_t name,uint32_t * offsetP,bool first,void * buf,uint32_t * szP)67 static void *eeDataGetEx(uint32_t name, uint32_t *offsetP, bool first, void *buf, uint32_t *szP)
68 {
69 uint32_t sz = 0;
70 void *data;
71
72 if (!eeIsValidName(name))
73 return false;
74
75 //find the data item
76 data = eeFind(name, offsetP, first, &sz);
77 if (!data)
78 return NULL;
79
80 if (buf && szP) { //get the data
81 if (sz > *szP)
82 sz = *szP;
83 *szP = sz;
84 memcpy(buf, data, sz);
85 }
86 else if (szP) //get size
87 *szP = sz;
88
89 return (uint32_t*)data - 1;
90 }
91
eeDataGet(uint32_t name,void * buf,uint32_t * szP)92 bool eeDataGet(uint32_t name, void *buf, uint32_t *szP)
93 {
94 uint32_t offset = 0;
95
96 return eeDataGetEx(name, &offset, false, buf, szP) != NULL;
97 }
98
eeDataGetAllVersions(uint32_t name,void * buf,uint32_t * szP,void ** stateP)99 void *eeDataGetAllVersions(uint32_t name, void *buf, uint32_t *szP, void **stateP)
100 {
101 uint32_t offset = *(uint32_t*)stateP;
102 void *addr = eeDataGetEx(name, &offset, true, buf, szP);
103 *(uint32_t*)stateP = offset;
104 return addr;
105 }
106
eeWrite(void * dst,const void * src,uint32_t len)107 static bool eeWrite(void *dst, const void *src, uint32_t len)
108 {
109 return BL.blProgramEe(dst, src, len, BL_FLASH_KEY1, BL_FLASH_KEY2);
110 }
111
eeDataSet(uint32_t name,const void * buf,uint32_t len)112 bool eeDataSet(uint32_t name, const void *buf, uint32_t len)
113 {
114 uint32_t sz, effectiveSz, info = name + len * (EE_DATA_NAME_MAX + 1);
115 bool ret = true;
116 void *space;
117
118 if (!eeIsValidName(name))
119 return false;
120
121 //find the empty space at the end of everything and make sure it is really empty (size == EE_DATA_LEN_MAX)
122 space = eeFind(EE_DATA_NAME_MAX, NULL, false, &sz);
123 if (!space || sz != EE_DATA_LEN_MAX)
124 return false;
125
126 //calculate effective size
127 effectiveSz = (len + 3) &~ 3;
128
129 //verify we have the space
130 if ((uint8_t*)__eedata_end - (uint8_t*)space < effectiveSz)
131 return false;
132
133 //write it in
134 ret = eeWrite(((uint32_t*)space) - 1, &info, sizeof(info)) && ret;
135 ret = eeWrite(space, buf, len) && ret;
136
137 return ret;
138 }
139
eeDataEraseOldVersion(uint32_t name,void * vaddr)140 bool eeDataEraseOldVersion(uint32_t name, void *vaddr)
141 {
142 uint32_t *addr = (uint32_t*)vaddr;
143 uint32_t v;
144
145 // sanity check
146 if (!eeIsValidName(name) || addr < __eedata_start || addr >= (__eedata_end - 1))
147 return false;
148
149 v = *addr;
150
151 //verify name
152 if ((v & EE_DATA_NAME_MAX) != name)
153 return false;
154
155 //clear name
156 v &=~ EE_DATA_NAME_MAX;
157
158 //store result
159 return eeWrite(addr, &v, sizeof(v));
160 }
161