KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
update.c
1 /*
2  * KM3NeT CLB v2 Firmware
3  * ----------------------
4  *
5  * Copyright 2013 KM3NeT Collaboration
6  *
7  * All Rights Reserved.
8  *
9  *
10  * File : update.c
11  * Created : 8 okt. 2013
12  * Author : Vincent van Beveren
13  */
14 #include "kernel/update.h"
15 
16 #include <stdio.h>
17 #include <string.h>
18 
19 #include "cfg_soc.h"
20 #include "errorcode.h"
21 
22 #include "dbg/show.h"
23 
24 #include "util/checksum.h"
25 #include "util/log.h"
26 
27 #include "kernel/err.h"
28 #include "drv/spi/sflash.h"
29 
30 LOG_DEF(Update);
31 
32 // #define UPDATE_SIMULATE
33 // #define STRICT_ORDER
34 
35 #define MAX_CHUNKS_LOST 10
36 
37 // the secret word
38 static const SfPassword UNLOCK_PASSWORD = {
39  0xD0, 0xAC, 0xCE, 0x55, // do access
40  0xDE, 0xAD, 0xBE, 0xEF }; // dead beef
41 
42 
43 const int updMaxImages = FLASH_MAX_IMAGES;
44 
45 static bool _updating = false;
46 static uint32_t _adler32;
47 static uint32_t _offaddr = 0x0;
48 static uint32_t _lastSec = 0xFFFFFFFF;
49 
50 static bool _failed = false;
51 
52 
53 static bool updProtectGolden() {
54  uint32_t addr = 0;
55 
56  for (addr = 0; addr < FLASH_SPACING; addr += sfInfo.sectorSize)
57  {
58  if (!sfProtect(addr)) return false;
59  }
60  return true;
61 }
62 
63 
64 bool updInit() {
65  // check if there is password protection,
66  // if not set it up.
68  logInfo("No password protection present, setting");
69 
70  if (!updProtectGolden()) return false;
71 
72  return sfSetPasswordOTP((SfPassword *)&UNLOCK_PASSWORD);
73  }
74  // check if its not locked, then lock it
75  if (!(sfInfo.sts & SF_INFO_STS_LOCKED)) {
76  sfLockUnlock(NULL);
77  }
78  return true;
79 }
80 
81 bool updStart(int imageIdx, uint32_t chunkCount)
82 {
83  if (_updating) return errSet(ERROR_CTX(E_INVSTATE));
84 
85 
86  if (chunkCount > UPD_CHUNK_MAX) return errSet(ERROR_CTX(E_INVARGUMENT));
87 
88  if (imageIdx == 0 && ( sfInfo.sts & SF_INFO_STS_LOCKED) ) {
89  return errSet(ERROR_CTX(E_UPD_PROTECTED));
90  }
91 
92  _adler32 = ADLER32_INIT_VAL;
93  _lastSec = 0xFFFFFFFF;
94  _failed = false;
95  _updating = true;
96  _offaddr = imageIdx * FLASH_SPACING;
97  logDebug("Starting update of image %d with %d chunks", imageIdx, chunkCount);
98  sfQuadEnable(true); // all our images use QUAD data width.
99  return true;
100 }
101 
102 bool updWrite(uint32_t chunkNo, uint8_t * chunk)
103 {
104  if (!_updating) return errSet(ERROR_CTX(E_INVSTATE));
105  if (_failed) return errSet(ERROR_CTX(E_INVSTATE));
106  if (chunkNo > UPD_CHUNK_MAX) return errSet(ERROR_CTX(E_INVARGUMENT));
107  uint32_t addr = _offaddr + chunkNo * UPD_CHUNK_SIZE;
108 
109 #ifdef STRICT_ORDER
110  if (_curaddr != _offaddr + chunkNo * UPD_CHUNK_SIZE)
111  {
112  _failed = true;
113  _curaddr = _offaddr + chunkNo * UPD_CHUNK_SIZE;
114  // received out of order .. should actually not really be a problem yet...
115  return errSet(ERROR(E_INVARGUMENT));
116  }
117 #endif
118 
119  if (_lastSec != (addr / sfInfo.sectorSize))
120  {
121  _lastSec = addr / sfInfo.sectorSize;
122  // _stdOut('E');
123 #ifndef UPDATE_SIMULATE
124  if (!sfErase(addr)) {
125 // _stdOut('!');
126  _failed = true;
127  return false;
128  }
129 #endif
130  }
131 
132 // _stdOut('P');
133 #ifndef UPDATE_SIMULATE
134  if (!sfProgXPage(addr, chunk, UPD_CHUNK_SIZE)) {
135  _failed = true;
136  return false;
137  }
138 #endif
139 
140  return true;
141 }
142 
143 bool updVerify(uint32_t imgNo, uint32_t chunkNo, uint8_t * chunk, bool * result)
144 {
145  if (chunkNo > UPD_CHUNK_MAX) return errSet(ERROR_CTX(E_INVARGUMENT));
146 
147  uint32_t addr = imgNo * FLASH_SPACING + chunkNo * UPD_CHUNK_SIZE;
148 
149  uint8_t vbuf[UPD_CHUNK_SIZE];
150 
151  if (!sfRead(addr, vbuf, UPD_CHUNK_SIZE)) return errRebase(_logModInfo.name);
152 
153  if (memcmp(chunk, vbuf, UPD_CHUNK_SIZE) != 0) *result = false;
154  else *result = true;
155 
156 // printf(*result ? "." : "X");
157 
158  return true;
159 }
160 
161 
162 
163 bool updEnd(uint32_t * chunkLostList, uint32_t * chunksCount)
164 {
165  if (!_updating) return errSet(ERROR_CTX(E_INVSTATE));
166  if (_failed) return errSet(ERROR_CTX(E_UPD_SOMECHUNKS));
167  logDebug("Update done");
168 
169  _updating = false;
170 
171  if (! (sfInfo.sts & SF_INFO_STS_LOCKED)) {
172  if (!updLock()) return false;
173  }
174 
175  return true;
176 }
177 
178 void updCancel()
179 {
180  _updating = false;
181 }
182 
183 bool updCheckImage(int index)
184 {
185  return true;
186 }
187 
188 bool updIsUpdating(int * index)
189 {
190  return _updating;
191 }
192 
193 bool updImgInfo(uint32_t imgNo, UpdImgInfo * imgInfo)
194 {
195  if (imgNo >= FLASH_MAX_IMAGES) return errSet(ERROR_CTX(E_INVARGUMENT));
196  if (imgInfo == NULL) return errSet(ERROR_CTX(E_INVARGUMENT));
197 
198  uint32_t addr = imgNo * FLASH_SPACING;
199  uint8_t hdr1[sizeof(UpdImgInfo) + 2];
200  uint8_t tag2[4];
201 
202 
203  if (!sfRead(addr, hdr1, sizeof(hdr1))) return errRebase(_logModInfo.name);
204  if (!sfRead(addr + 292, tag2, sizeof(tag2))) return errRebase(_logModInfo.name);
205 
206  if (hdr1[0] == 0xDA && hdr1[1] == 0x7A)
207  {
208  memcpy(imgInfo, &hdr1[2], sizeof(UpdImgInfo));
209  } else if (tag2[0] == 0x11 && tag2[1] == 0x22 && tag2[2] == 0x00 && tag2[3] == 0x44)
210  {
211  // Okay, there is an image, but we don't know what it is
212  imgInfo->fwRev = 0;
213  imgInfo->swRev = 0;
214  imgInfo->imgType = UPD_IMGTYPE_UNKNOWN;
215  } else {
216  imgInfo->fwRev = 0;
217  imgInfo->swRev = 0;
218  imgInfo->imgType = UPD_IMGTYPE_NONE;
219  }
220 
221  return true;
222 }
223 
224 
225 bool updUnlock() {
226  if (!sfLockUnlock((SfPassword *)&UNLOCK_PASSWORD)) return false;
227  return sfUnProtect();
228 }
229 
230 bool updLock() {
231  if (!updProtectGolden()) return false;
232  return sfLockUnlock(NULL);
233 }
234 
bool updVerify(uint32_t imgNo, uint32_t chunkNo, uint8_t *chunk, bool *result)
Verify a chunk.
Definition: update.c:143
bool sfQuadEnable(bool enable)
Quad enable,.
Definition: sflash.c:442
bool sfLockUnlock(SfPassword *password)
Unlocks or locks the flash with the specified password.
Definition: sflash.c:645
uint8_t SfPassword[8]
Serial Flash password.
Definition: sflash.h:57
bool updWrite(uint32_t chunkNo, uint8_t *chunk)
Write a update chunk.
Definition: update.c:102
Defines the configuration of the LM32 SOC for the CLBv2.
#define E_UPD_SOMECHUNKS
Some chunks lost, check chunkLostList.
Definition: update.h:35
#define ADLER32_INIT_VAL
Value to which the Adler32 checksum should be initialized.
Definition: checksum.h:30
bool updUnlock()
Unlocks the golden image for writing.
Definition: update.c:225
bool updImgInfo(uint32_t imgNo, UpdImgInfo *imgInfo)
Retrieve image information for the specified location.
Definition: update.c:193
#define UPD_IMGTYPE_NONE
There is no image at the specified location.
Definition: update.h:134
bool updIsUpdating(int *index)
Returns whether or not the storage is in update mode.
Definition: update.c:188
int8_t imgType
Image type.
Definition: update.h:145
bool updInit()
Initializes the update module.
Definition: update.c:64
#define SF_INFO_STS_PASSWORD_PROTECT
Whether (part of) the flash is password.
Definition: sflash.h:52
bool updEnd(uint32_t *chunkLostList, uint32_t *chunksCount)
Ends the update.
Definition: update.c:163
SfInfo sfInfo
Flash info, only valid after successful initialization.
Definition: sflash.c:161
uint32_t sectorSize
Sector size in bytes.
Definition: sflash.h:62
bool updLock()
Locks the golden image for writing.
Definition: update.c:230
#define E_INVSTATE
Generic error: Module is in a state in which.
Definition: errorcode.h:103
#define E_INVARGUMENT
Generic error: invalid argument.
Definition: errorcode.h:112
bool updStart(int imageIdx, uint32_t chunkCount)
Starts an image update.
Definition: update.c:81
Manages the global system error.
bool sfErase(uint32_t address)
Erase a sector in flash.
Definition: sflash.c:564
#define SF_INFO_STS_LOCKED
Whether part of the flash is locked.
Definition: sflash.h:54
uint8_t sts
Device status, see SF_INFO_STS_*.
Definition: sflash.h:69
void updCancel()
Aborts the update.
Definition: update.c:178
uint32_t swRev
Software revision.
Definition: update.h:144
bool sfSetPasswordOTP(SfPassword *password)
Password protects specific sectors from being modified.
Definition: sflash.c:589
#define UPD_IMGTYPE_UNKNOWN
There is an image, but it has no meta-data.
Definition: update.h:135
uint32_t fwRev
Firmware revision.
Definition: update.h:143
bool sfProtect(uint32_t address)
Protects a specific sector from being erased or programmed.
Definition: sflash.c:672
bool sfProgXPage(uint32_t address, uint8_t *data, uint32_t count)
Program cross pages.
Definition: sflash.c:547
This module is responsible for distributing error codes.
#define LOG_DEF(NAME,...)
Define a logger for a module.
Definition: log.h:129
const int updMaxImages
Maximum no of images.
Definition: update.c:43
static bool errRebase(const char *name)
Rebases the cause of the error message.
Definition: err.h:104
bool sfRead(uint32_t address, uint8_t *data, uint32_t count)
Read from a specific address in flash.
Definition: sflash.c:491
This module provides checksum functions.
bool errSet(uint32_t code, const char *error, const char *name)
Sets an error.
#define ERROR(CODE,...)
Expands an error code to an error code with a description (if ERROR_W_DESCR is declared).
This driver implements access to the Serial Flash.
#define UPD_CHUNK_SIZE
chunk size for updates, in bytes
Definition: update.h:32
Implements a generic logger facility.
#define E_UPD_PROTECTED
Protection is not cleared.
Definition: update.h:44
#define logInfo(MSG,...)
Write a log message with formatting on info level.
Definition: log.h:202
bool sfUnProtect()
Unprotects the entire flash array.
Definition: sflash.c:690
Facilitates the update process.