Reduce bashisms
[bcusdk.git] / common / loadimage.cpp
blobefc0b87a8b4dbab567cef5cf9d15740f923b8a65
1 /*
2 EIBD eib bus access and management daemon
3 Copyright (C) 2005-2009 Martin Koegler <mkoegler@auto.tuwien.ac.at>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "loadimage.h"
21 #include "image.h"
23 static void
24 GenAlloc (CArray & req, uint16_t start, uint16_t len, uint8_t access,
25 uint8_t type, bool check)
27 const uchar zero[10] = { 0 };
28 req.set (zero, 10);
29 req[0] = 0x03;
30 req[2] = (start >> 8) & 0xff;
31 req[3] = (start) & 0xff;
32 req[4] = (len >> 8) & 0xff;
33 req[5] = (len) & 0xff;
34 req[6] = access;
35 req[7] = type;
36 req[8] = check ? 0x80 : 0x00;
39 typedef struct
41 uint16_t start;
42 uint16_t len;
43 } Segment;
45 static int
46 AddSegmentOverlap (Array < Segment > &s, uint16_t start, uint16_t len)
48 int i;
49 if (!len)
50 return 1;
51 for (i = 0; i < s (); i++)
53 if (start >= s[i].start && start < s[i].start + s[i].len)
54 return 0;
55 if (s[i].start >= start && s[i].start < start + len)
56 return 0;
58 Segment s1;
59 s1.start = start;
60 s1.len = len;
61 if (len)
62 s.add (s1);
63 return 1;
66 BCU_LOAD_RESULT
67 PrepareLoadImage (const CArray & im, BCUImage * &img)
69 Array < Segment > seg;
70 img = 0;
71 Image *i = Image::fromArray (im);
72 if (!i)
73 return IMG_UNRECOG_FORMAT;
75 if (!i->isValid ())
77 delete i;
78 return IMG_INVALID_FORMAT;
81 STR_BCUType *b = (STR_BCUType *) i->findStream (S_BCUType);
82 if (!b)
84 delete i;
85 return IMG_NO_BCUTYPE;
87 STR_Code *c = (STR_Code *) i->findStream (S_Code);
88 if (!c)
90 delete i;
91 return IMG_NO_CODE;
93 if (b->bcutype == 0x0012)
95 STR_BCU1Size *s = (STR_BCU1Size *) i->findStream (S_BCU1Size);
96 if (!s)
98 delete i;
99 return IMG_NO_SIZE;
102 if (s->datasize + s->bsssize + s->stacksize > 18)
104 delete i;
105 return IMG_LODATA_OVERFLOW;
107 if (s->textsize > 0xfe)
109 delete i;
110 return IMG_TEXT_OVERFLOW;
113 if (s->textsize != c->code ())
115 delete i;
116 return IMG_WRONG_SIZE;
119 if (s->textsize < 0x18)
121 delete i;
122 return IMG_NO_ADDRESS;
124 if (c->code[8] < 8 || c->code[8] > c->code () + 1)
126 delete i;
127 return IMG_WRONG_CHECKLIM;
129 img = new BCUImage;
130 img->code = c->code;
131 img->BCUType = BCUImage::B_bcu1;
132 img->addr = (c->code[0x17] << 8) | (c->code[0x18]);
134 return IMG_IMAGE_LOADABLE;
136 if (b->bcutype == 0x0020 || b->bcutype == 0x0021)
138 STR_BCU2Size *s = (STR_BCU2Size *) i->findStream (S_BCU2Size);
139 if (!s)
141 delete i;
142 return IMG_NO_SIZE;
144 if (s->lo_datasize + s->lo_bsssize > 18)
146 delete i;
147 return IMG_LODATA_OVERFLOW;
149 if (s->hi_datasize + s->hi_bsssize > 24)
151 delete i;
152 return IMG_HIDATA_OVERFLOW;
154 if (s->textsize > 0x36f)
156 delete i;
157 return IMG_TEXT_OVERFLOW;
160 if (s->textsize != c->code ())
162 delete i;
163 return IMG_WRONG_SIZE;
166 if (s->textsize < 0x18)
168 delete i;
169 return IMG_NO_ADDRESS;
171 STR_BCU2Start *s1 = (STR_BCU2Start *) i->findStream (S_BCU2Start);
172 if (!s1)
174 delete i;
175 return IMG_NO_START;
177 if (s1->addrtab_start != 0x116 || s1->addrtab_size < 4)
179 delete i;
180 return IMG_WRONG_ADDRTAB;
182 if (s1->addrtab_size > 0xff)
184 delete i;
185 return IMG_ADDRTAB_OVERFLOW;
188 AddSegmentOverlap (seg, s1->addrtab_start, s1->addrtab_size);
190 if (!AddSegmentOverlap (seg, s1->assoctab_start, s1->assoctab_size))
192 delete i;
193 return IMG_OVERLAP_ASSOCTAB;
195 if (s1->assoctab_size > 0xff)
197 delete i;
198 return IMG_ADDRTAB_OVERFLOW;
200 if (s1->readonly_end < s1->readonly_start)
202 delete i;
203 return IMG_NEGATIV_TEXT_SIZE;
205 if (!AddSegmentOverlap
206 (seg, s1->readonly_start, s1->readonly_end - s1->readonly_start))
208 delete i;
209 return IMG_OVERLAP_TEXT;
211 if (s1->param_end < s1->param_start)
213 delete i;
214 return IMG_NEGATIV_TEXT_SIZE;
216 if (s1->eeprom_end < s1->eeprom_start)
218 delete i;
219 return IMG_NEGATIV_TEXT_SIZE;
221 if (!AddSegmentOverlap
222 (seg, s1->eeprom_start, s1->eeprom_end - s1->eeprom_start))
224 delete i;
225 return IMG_OVERLAP_EEPROM;
227 if (!AddSegmentOverlap
228 (seg, s1->param_start, s1->param_end - s1->param_start))
230 delete i;
231 return IMG_OVERLAP_PARAM;
233 if (s1->obj_count > 0xff)
235 delete i;
236 return IMG_OBJTAB_OVERFLOW;
238 if (s1->param_end > c->code () + 0x100)
240 delete i;
241 return IMG_WRONG_LOADCTL;
244 STR_BCU2Key *s2 = (STR_BCU2Key *) i->findStream (S_BCU2Key);
245 if (s2 && s2->keys () != 3)
247 delete i;
248 return IMG_INVALID_KEY;
251 img = new BCUImage;
252 img->code = c->code;
253 img->BCUType =
254 (b->bcutype == 0x0020 ? BCUImage::B_bcu20 : BCUImage::B_bcu21);
255 img->addr = (c->code[0x17] << 8) | (c->code[0x18]);
257 if (s2)
259 img->installkey = s2->installkey;
260 img->keys = s2->keys;
262 else
264 img->installkey = 0xFFFFFFFF;
265 img->keys.resize (3);
266 img->keys[0] = 0xFFFFFFFF;
267 img->keys[1] = 0xFFFFFFFF;
268 img->keys[2] = 0xFFFFFFFF;
271 const uchar zero[10] = { 0 };
272 EIBLoadRequest r;
273 /*unload */
274 r.obj = 1;
275 r.prop = 5;
276 r.start = 1;
277 r.memaddr = 0xffff;
278 r.req.set (zero, 10);
279 r.req[0] = 0x04;
280 r.result.resize (1);
281 r.result[0] = 0x00;
282 r.error = IMG_UNLOAD_ADDR;
283 img->load.add (r);
284 r.obj = 2;
285 r.error = IMG_UNLOAD_ASSOC;
286 img->load.add (r);
287 r.obj = 3;
288 r.error = IMG_UNLOAD_PROG;
289 img->load.add (r);
291 /* loadaddrtab */
292 r.req.set (zero, 10);
293 r.obj = 1;
294 r.req[0] = 0x01;
295 r.result[0] = 0x02;
296 r.error = IMG_LOAD_ADDR;
297 img->load.add (r);
299 GenAlloc (r.req, s1->addrtab_start, s1->addrtab_size, 0x31, 0x03, 1);
300 r.memaddr = s1->addrtab_start;
301 r.len = 1;
302 r.error = IMG_WRITE_ADDR;
303 img->load.add (r);
305 r.obj = 0xff;
306 r.memaddr += 3;
307 r.len = s1->addrtab_size - 4;
308 img->load.add (r);
310 r.obj = 1;
311 r.memaddr = 0xffff;
312 r.req[0] = 0x03;
313 r.req[1] = 0x02;
314 r.req[2] = (s1->addrtab_start >> 8) & 0xff;
315 r.req[3] = (s1->addrtab_start) & 0xff;
316 r.req[4] = c->code[0x09];
317 r.req.setpart (c->code.array () + 0x03, 5, 5);
318 r.error = IMG_SET_ADDR;
319 img->load.add (r);
321 r.req.set (zero, 10);
322 r.req[0] = 0x02;
323 r.result[0] = 0x01;
324 r.error = IMG_FINISH_ADDR;
325 img->load.add (r);
327 /* loadassoctab */
328 r.req.set (zero, 10);
329 r.obj = 2;
330 r.req[0] = 0x01;
331 r.result[0] = 0x02;
332 r.error = IMG_LOAD_ASSOC;
333 img->load.add (r);
335 GenAlloc (r.req, s1->assoctab_start, s1->assoctab_size, 0x31, 0x03, 1);
336 r.memaddr = s1->assoctab_start;
337 r.len = s1->assoctab_size - 1;
338 r.error = IMG_WRITE_ASSOC;
339 img->load.add (r);
341 r.memaddr = 0xffff;
342 r.req[0] = 0x03;
343 r.req[1] = 0x02;
344 r.req[2] = (s1->assoctab_start >> 8) & 0xff;
345 r.req[3] = (s1->assoctab_start) & 0xff;
346 r.req[4] = c->code[0x09];
347 r.req.setpart (c->code.array () + 0x03, 5, 5);
348 r.error = IMG_SET_ASSOC;
349 img->load.add (r);
351 r.req.set (zero, 10);
352 r.req[0] = 0x02;
353 r.result[0] = 0x01;
354 r.error = IMG_FINISH_ASSOC;
355 img->load.add (r);
357 /* loadproctab */
358 r.req.set (zero, 10);
359 r.obj = 3;
360 r.req[0] = 0x01;
361 r.result[0] = 0x02;
362 r.error = IMG_LOAD_PROG;
363 img->load.add (r);
365 GenAlloc (r.req, 0x00C8, 0x0018, 0x32, 0x01, 0);
366 r.error = IMG_ALLOC_LORAM;
367 img->load.add (r);
369 GenAlloc (r.req, 0x0972, 0x004A, 0x32, 0x02, 0);
370 r.error = IMG_ALLOC_HIRAM;
371 img->load.add (r);
373 GenAlloc (r.req, 0x0100, 0x0016, 0x32, 0x03, 0);
374 r.error = IMG_ALLOC_INIT;
375 r.len = 0x001;
376 r.memaddr = 0x100;
377 img->load.add (r);
379 r.obj = 0xff;
380 r.memaddr = 0x103;
381 r.len = 0x13;
382 img->load.add (r);
383 r.obj = 3;
385 GenAlloc (r.req, s1->readonly_start,
386 s1->readonly_end - s1->readonly_start, 0x30, 0x03, 1);
387 r.error = IMG_ALLOC_RO;
388 r.len = s1->readonly_end - s1->readonly_start - 1;
389 r.memaddr = s1->readonly_start;
390 if (r.len)
391 img->load.add (r);
393 GenAlloc (r.req, s1->eeprom_start, s1->eeprom_end - s1->eeprom_start,
394 0x31, 0x03, 0);
395 r.error = IMG_ALLOC_EEPROM;
396 r.len = s1->eeprom_end - s1->eeprom_start;
397 r.memaddr = s1->eeprom_start;
398 if (r.len)
399 img->load.add (r);
401 GenAlloc (r.req, s1->param_start, s1->param_end - s1->param_start, 0x32,
402 0x03, 1);
403 r.error = IMG_ALLOC_PARAM;
404 r.len = s1->param_end - s1->param_start;
405 r.memaddr = s1->param_start;
406 if (r.len > 1)
407 img->load.add (r);
409 r.memaddr = 0xffff;
410 r.req[0] = 0x03;
411 r.req[1] = 0x02;
412 r.req[2] = (s1->runaddr >> 8) & 0xff;
413 r.req[3] = (s1->runaddr) & 0xff;
414 r.req[4] = c->code[0x09];
415 r.req.setpart (c->code.array () + 0x03, 5, 5);
416 r.error = IMG_SET_PROG;
417 img->load.add (r);
419 r.req.set (zero, 10);
420 r.req[0] = 0x03;
421 r.req[1] = 0x03;
422 r.req[2] = (s1->initaddr >> 8) & 0xff;
423 r.req[3] = (s1->initaddr) & 0xff;
424 r.req[4] = (s1->saveaddr >> 8) & 0xff;
425 r.req[5] = (s1->saveaddr) & 0xff;
426 r.req[6] = (s1->sphandler >> 8) & 0xff;
427 r.req[7] = (s1->sphandler) & 0xff;
428 r.error = IMG_SET_TASK_PTR;
429 img->load.add (r);
431 r.req.set (zero, 10);
432 r.req[0] = 0x03;
433 r.req[1] = 0x04;
434 r.req[2] = (s1->obj_ptr >> 8) & 0xff;
435 r.req[3] = (s1->obj_ptr) & 0xff;
436 r.req[4] = (s1->obj_count) & 0xff;
437 r.error = IMG_SET_OBJ;
438 img->load.add (r);
440 r.req.set (zero, 10);
441 r.req[0] = 0x03;
442 r.req[1] = 0x05;
443 r.req[2] = (s1->appcallback >> 8) & 0xff;
444 r.req[3] = (s1->appcallback) & 0xff;
445 r.req[4] = (s1->groupobj_ptr >> 8) & 0xff;
446 r.req[5] = (s1->groupobj_ptr) & 0xff;
447 r.req[6] = (s1->seg0 >> 8) & 0xff;
448 r.req[7] = (s1->seg0) & 0xff;
449 r.req[8] = (s1->seg1 >> 8) & 0xff;
450 r.req[9] = (s1->seg1) & 0xff;
451 r.error = IMG_SET_TASK2;
452 img->load.add (r);
454 r.req.set (zero, 10);
455 r.req[0] = 0x02;
456 r.result[0] = 0x01;
457 r.error = IMG_FINISH_PROC;
458 img->load.add (r);
460 return IMG_IMAGE_LOADABLE;
464 delete i;
465 return IMG_UNKNOWN_BCUTYPE;
468 #define _(A) (A)
470 String
471 decodeBCULoadResult (BCU_LOAD_RESULT r)
473 switch (r)
475 case IMG_UNKNOWN_ERROR:
476 return _("unknown error");
477 break;
478 case IMG_UNRECOG_FORMAT:
479 return _("data not regcognized as image");
480 break;
481 case IMG_INVALID_FORMAT:
482 return _("invalid streams in the image");
483 break;
484 case IMG_NO_BCUTYPE:
485 return _("no bcu type specified");
486 break;
487 case IMG_UNKNOWN_BCUTYPE:
488 return _("don't know how to load the bcutype");
489 break;
490 case IMG_NO_CODE:
491 return _("no text segment found");
492 break;
493 case IMG_NO_SIZE:
494 return _("size information not found");
495 break;
496 case IMG_LODATA_OVERFLOW:
497 return _("too many data for low-ram");
498 break;
499 case IMG_HIDATA_OVERFLOW:
500 return _("too many data for hi-ram");
501 break;
502 case IMG_TEXT_OVERFLOW:
503 return _("too many data for eeprom");
504 break;
505 case IMG_IMAGE_LOADABLE:
506 return _("Image is loadable");
507 break;
508 case IMG_NO_ADDRESS:
509 return _("no address found in the image");
510 break;
511 case IMG_WRONG_SIZE:
512 return _("unexpected size of the text segment");
513 break;
514 case IMG_NO_DEVICE_CONNECTION:
515 return _("connection to the device failed");
516 break;
517 case IMG_MASK_READ_FAILED:
518 return _("read of mask version failed");
519 break;
520 case IMG_WRONG_MASK_VERSION:
521 return _("incompatible mask version");
522 break;
523 case IMG_CLEAR_ERROR:
524 return _("reseting of RunFlags failed");
525 break;
526 case IMG_RESET_ADDR_TAB:
527 return _("reseting of the address table failed");
528 break;
529 case IMG_LOAD_HEADER:
530 return _("loading of the header failed");
531 break;
532 case IMG_LOAD_MAIN:
533 return _("loading of the code in the eeprom failed");
534 break;
535 case IMG_ZERO_RAM:
536 return _("cleaning the ram failed");
537 break;
538 case IMG_FINALIZE_ADDR_TAB:
539 return _("finalizing the address table failed");
540 break;
541 case IMG_PREPARE_RUN:
542 return _("setting the RunFlags failed");
543 break;
544 case IMG_RESTART:
545 return _("restart failed");
546 break;
547 case IMG_LOADED:
548 return _("image successful loaded");
549 break;
550 case IMG_NO_START:
551 return _("no BCU2 load control information present");
552 break;
553 case IMG_WRONG_ADDRTAB:
554 return _("wrong start address of the address table");
555 break;
556 case IMG_ADDRTAB_OVERFLOW:
557 return _("address table too big");
558 break;
559 case IMG_OVERLAP_ASSOCTAB:
560 return _("association table overlaps with an other segment");
561 break;
562 case IMG_OVERLAP_TEXT:
563 return _("text segement overlaps with an other segment");
564 break;
565 case IMG_NEGATIV_TEXT_SIZE:
566 return _("segment end < text segment");
567 break;
568 case IMG_OVERLAP_PARAM:
569 return _("param segment overlaps with an other segment");
570 break;
571 case IMG_OVERLAP_EEPROM:
572 return _("eeprom segment overlaps with an other segment");
573 break;
574 case IMG_OBJTAB_OVERFLOW:
575 return _("too many objects");
576 break;
577 case IMG_WRONG_LOADCTL:
578 return _("param end not in the text segment");
579 break;
580 case IMG_UNLOAD_ADDR:
581 return _("error unloading address table");
582 break;
583 case IMG_UNLOAD_ASSOC:
584 return _("error unloading assocation table");
585 break;
586 case IMG_UNLOAD_PROG:
587 return _("error unloading user programm");
588 break;
589 case IMG_LOAD_ADDR:
590 return _("error start loading address table");
591 break;
592 case IMG_WRITE_ADDR:
593 return _("error allocation address table");
594 break;
595 case IMG_SET_ADDR:
596 return _("error setting address table start");
597 break;
598 case IMG_FINISH_ADDR:
599 return _("error finishing address table");
600 break;
601 case IMG_LOAD_ASSOC:
602 return _("error start loading association table");
603 break;
604 case IMG_WRITE_ASSOC:
605 return _("error allocation assocation table");
606 break;
607 case IMG_SET_ASSOC:
608 return _("error setting assocation table start");
609 break;
610 case IMG_FINISH_ASSOC:
611 return _("error finishing assocation table");
612 break;
613 case IMG_LOAD_PROG:
614 return _("error start loading programm");
615 break;
616 case IMG_ALLOC_LORAM:
617 return _("error allocation low ram");
618 break;
619 case IMG_ALLOC_HIRAM:
620 return _("error allocation high ram");
621 break;
622 case IMG_ALLOC_INIT:
623 return _("error allocation config section");
624 break;
625 case IMG_ALLOC_RO:
626 return _("error loading text segment");
627 break;
628 case IMG_ALLOC_EEPROM:
629 return _("error loading eeprom segment");
630 break;
631 case IMG_ALLOC_PARAM:
632 return _("error loading parameter segement");
633 break;
634 case IMG_SET_PROG:
635 return _("error setting programm entry");
636 break;
637 case IMG_SET_TASK_PTR:
638 return _("error setting task pointer");
639 break;
640 case IMG_SET_OBJ:
641 return _("error setting object pointer");
642 break;
643 case IMG_SET_TASK2:
644 return _("error setting group object pointer");
645 break;
646 case IMG_FINISH_PROC:
647 return _("error finishing application programm");
648 break;
649 case IMG_WRONG_CHECKLIM:
650 return _("wrong check limit");
651 break;
652 case IMG_AUTHORIZATION_FAILED:
653 return _("authorization failed");
654 break;
655 case IMG_INVALID_KEY:
656 return _("invalid key information");
657 break;
658 case IMG_KEY_WRITE:
659 return _("key write failed");
660 break;
662 default:
663 return _("errorcode not defined");