• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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