managementclient.cpp
1 /* 2 EIBD eib bus access and management daemon 3 Copyright (C) 2005-2011 Martin Koegler <mkoegler@auto.tuwien.ac.at> 4 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. 9 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. 14 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20 #include "managementclient.h" 21 22 #include "loadimage.h" 23 #include "management.h" 24 25 void 26 ReadIndividualAddresses (ClientConnPtr c, uint8_t *buf, size_t len) 27 { 28 Layer7_Broadcast b (c->t); 29 if (!b.init (c->l3)) 30 { 31 c->sendreject (EIB_PROCESSING_ERROR); 32 return; 33 } 34 CArray erg; 35 std::vector < eibaddr_t > e = b.A_IndividualAddress_Read (c->t); 36 erg.resize (2 + 2 * e.size()); 37 EIBSETTYPE (erg, EIB_M_INDIVIDUAL_ADDRESS_READ); 38 for (unsigned i = 0; i < e.size(); i++) 39 { 40 erg[2 + i * 2] = (e[i] >> 8) & 0xff; 41 erg[2 + i * 2 + 1] = (e[i]) & 0xff; 42 } 43 c->sendmessage (erg.size(), erg.data()); 44 } 45 46 void 47 ChangeProgMode (ClientConnPtr c, uint8_t *buf, size_t len) 48 { 49 eibaddr_t dest; 50 uint8_t res[3]; 51 int i; 52 EIBSETTYPE (res, EIB_PROG_MODE); 53 res[2] = 0; 54 if (c->size < 5) 55 { 56 c->sendreject (); 57 return; 58 } 59 dest = (c->buf[2] << 8) | (c->buf[3]); 60 Management_Connection m = Management_Connection (c->t, dest); 61 if (!m.init (c->l3)) 62 { 63 c->sendreject (EIB_PROCESSING_ERROR); 64 return; 65 } 66 switch (c->buf[4]) 67 { 68 case 0: 69 if (m.X_Progmode_Off () == -1) 70 c->sendreject (); 71 else 72 c->sendmessage (3, res); 73 break; 74 case 1: 75 if (m.X_Progmode_On () == -1) 76 c->sendreject (); 77 else 78 c->sendmessage (3, res); 79 break; 80 case 2: 81 if (m.X_Progmode_Toggle () == -1) 82 c->sendreject (); 83 else 84 c->sendmessage (3, res); 85 break; 86 case 3: 87 if ((i = m.X_Progmode_Status ()) == -1) 88 c->sendreject (); 89 else 90 { 91 res[2] = i; 92 c->sendmessage (3, res); 93 } 94 break; 95 default: 96 c->sendreject (); 97 } 98 } 99 100 void 101 GetMaskVersion (ClientConnPtr c, uint8_t *buf, size_t len) 102 { 103 eibaddr_t dest; 104 uint8_t res[4]; 105 uint16_t maskver; 106 EIBSETTYPE (res, EIB_MASK_VERSION); 107 res[2] = 0; 108 if (c->size < 4) 109 { 110 c->sendreject (); 111 return; 112 } 113 114 dest = (c->buf[2] << 8) | (c->buf[3]); 115 Management_Connection m = Management_Connection (c->t, dest); 116 if (!m.init (c->l3)) 117 { 118 c->sendreject (EIB_PROCESSING_ERROR); 119 return; 120 } 121 if (m.A_Device_Descriptor_Read (maskver) == -1) 122 c->sendreject (); 123 else 124 { 125 res[2] = (maskver >> 8) & 0xff; 126 res[3] = (maskver) & 0xff; 127 c->sendmessage (4, res); 128 } 129 } 130 131 void 132 WriteIndividualAddress (ClientConnPtr c, uint8_t *buf, size_t len) 133 { 134 eibaddr_t dest; 135 uint16_t maskver; 136 if (c->size < 4) 137 { 138 c->sendreject (); 139 return; 140 } 141 142 dest = (c->buf[2] << 8) | (c->buf[3]); 143 Layer7_Broadcast b (c->t); 144 if (!b.init (c->l3)) 145 { 146 c->sendreject (EIB_PROCESSING_ERROR); 147 return; 148 } 149 { 150 Management_Connection m = Management_Connection (c->t, dest); 151 if (!m.init (c->l3)) 152 { 153 c->sendreject (EIB_PROCESSING_ERROR); 154 return; 155 } 156 if (m.A_Device_Descriptor_Read (maskver) != -1) 157 { 158 c->sendreject (EIB_ERROR_ADDR_EXISTS); 159 return; 160 } 161 } 162 std::vector < eibaddr_t > addr = b.A_IndividualAddress_Read (c->t); 163 if (addr.size() > 1) 164 { 165 c->sendreject (EIB_ERROR_MORE_DEVICE); 166 return; 167 } 168 if (addr.size() == 0) 169 { 170 c->sendreject (EIB_ERROR_TIMEOUT); 171 return; 172 } 173 b.A_IndividualAddress_Write (dest); 174 // wait 100ms 175 pth_usleep (100000); 176 177 Management_Connection m1 = Management_Connection (c->t, dest); 178 if (!m1.init (c->l3)) 179 { 180 c->sendreject (EIB_PROCESSING_ERROR); 181 return; 182 } 183 if (m1.A_Device_Descriptor_Read (maskver) == -1) 184 { 185 c->sendreject (EIB_PROCESSING_ERROR); 186 return; 187 } 188 if (m1.X_Progmode_Off () == -1) 189 { 190 c->sendreject (EIB_PROCESSING_ERROR); 191 return; 192 } 193 c->sendreject (EIB_M_INDIVIDUAL_ADDRESS_WRITE); 194 } 195 196 ManagementConnection::ManagementConnection (ClientConnPtr c, uint8_t *buf, size_t len) 197 { 198 eibaddr_t dest; 199 uint16_t maskver; 200 int16_t val; 201 uint8_t buf[10]; 202 int i; 203 eibkey_type key; 204 205 if (c->size < 4) 206 { 207 c->sendreject (); 208 return; 209 } 210 211 dest = (c->buf[2] << 8) | (c->buf[3]); 212 Management_Connection m = Management_Connection (c->t, dest); 213 if (!m.init (c->l3)) 214 { 215 c->sendreject (EIB_PROCESSING_ERROR); 216 return; 217 } 218 if (m.A_Device_Descriptor_Read (maskver) == -1) 219 { 220 c->sendreject (); 221 return; 222 } 223 c->sendreject (EIB_MC_CONNECTION); 224 do 225 { 226 i = c->readmessage (); 227 if (i != -1) 228 switch (EIBTYPE (c->buf)) 229 { 230 case EIB_MC_PROG_MODE: 231 if (c->size < 3) 232 { 233 c->sendreject (); 234 break; 235 } 236 EIBSETTYPE (buf, EIB_MC_PROG_MODE); 237 buf[2] = 0; 238 switch (c->buf[2]) 239 { 240 case 0: 241 if (m.X_Progmode_Off () == -1) 242 c->sendreject (); 243 else 244 c->sendmessage (3, buf); 245 break; 246 case 1: 247 if (m.X_Progmode_On () == -1) 248 c->sendreject (); 249 else 250 c->sendmessage (3, buf); 251 break; 252 case 2: 253 if (m.X_Progmode_Toggle () == -1) 254 c->sendreject (); 255 else 256 c->sendmessage (3, buf); 257 break; 258 case 3: 259 if ((i = m.X_Progmode_Status ()) == -1) 260 c->sendreject (); 261 else 262 { 263 buf[2] = i; 264 c->sendmessage (3, buf); 265 } 266 break; 267 default: 268 c->sendreject (); 269 } 270 break; 271 case EIB_MC_MASK_VERSION: 272 if (m.A_Device_Descriptor_Read (maskver) == -1) 273 c->sendreject (); 274 else 275 { 276 EIBSETTYPE (buf, EIB_MC_MASK_VERSION); 277 buf[2] = (maskver >> 8) & 0xff; 278 buf[3] = (maskver) & 0xff; 279 c->sendmessage (4, buf); 280 } 281 break; 282 case EIB_MC_PEI_TYPE: 283 if (m.X_Get_PEIType (val) == -1) 284 c->sendreject (); 285 else 286 { 287 EIBSETTYPE (buf, EIB_MC_PEI_TYPE); 288 buf[2] = (val >> 8) & 0xff; 289 buf[3] = (val) & 0xff; 290 c->sendmessage (4, buf); 291 } 292 break; 293 case EIB_MC_ADC_READ: 294 if (c->size < 4) 295 { 296 c->sendreject (); 297 break; 298 } 299 if (m.A_ADC_Read (c->buf[2], c->buf[3], val) == -1) 300 c->sendreject (); 301 else 302 { 303 EIBSETTYPE (buf, EIB_MC_ADC_READ); 304 buf[2] = (val >> 8) & 0xff; 305 buf[3] = (val) & 0xff; 306 c->sendmessage (4, buf); 307 } 308 break; 309 310 case EIB_MC_READ: 311 if (c->size < 6) 312 { 313 c->sendreject (); 314 break; 315 } 316 { 317 memaddr_t addr = (c->buf[2] << 8) | (c->buf[3]); 318 unsigned len = (c->buf[4] << 8) | (c->buf[5]); 319 CArray data, erg; 320 if (m.X_Memory_Read_Block (addr, len, data) == -1) 321 c->sendreject (); 322 else 323 { 324 erg.resize (6); 325 EIBSETTYPE (erg, EIB_MC_READ); 326 erg.setpart (data, 2); 327 c->sendmessage (erg.size(), erg.data()); 328 } 329 } 330 break; 331 332 case EIB_MC_WRITE: 333 if (c->size < 6) 334 { 335 c->sendreject (); 336 break; 337 } 338 { 339 memaddr_t addr = (c->buf[2] << 8) | (c->buf[3]); 340 unsigned len = (c->buf[4] << 8) | (c->buf[5]); 341 if (c->size < len + 6) 342 { 343 c->sendreject (); 344 break; 345 } 346 i = m.X_Memory_Write_Block (addr, CArray (c->buf + 6, len)); 347 if (i == -2) 348 c->sendreject (EIB_ERROR_VERIFY); 349 else if (i != 0) 350 c->sendreject (EIB_PROCESSING_ERROR); 351 else 352 c->sendreject (EIB_MC_WRITE); 353 } 354 break; 355 356 case EIB_MC_PROP_READ: 357 if (c->size < 7) 358 { 359 c->sendreject (); 360 break; 361 } 362 { 363 CArray data, erg; 364 if (m.A_Property_Read (c->buf[2], c->buf[3], 365 (c->buf[4] << 8) | c->buf[5], c->buf[6], 366 data) == -1) 367 c->sendreject (); 368 else 369 { 370 erg.resize (2); 371 EIBSETTYPE (erg, EIB_MC_PROP_READ); 372 erg.setpart (data, 2); 373 c->sendmessage (erg.size(), erg.data()); 374 } 375 } 376 break; 377 378 case EIB_MC_PROP_WRITE: 379 if (c->size < 7) 380 { 381 c->sendreject (); 382 break; 383 } 384 { 385 CArray data, erg; 386 if (m.A_Property_Write (c->buf[2], c->buf[3], 387 (c->buf[4] << 8) | c->buf[5], c->buf[6], 388 CArray (c->buf + 7, c->size - 7), 389 erg) == -1) 390 c->sendreject (); 391 else 392 { 393 erg.resize (2); 394 EIBSETTYPE (erg, EIB_MC_PROP_WRITE); 395 erg.setpart (data, 2); 396 c->sendmessage (erg.size(), erg.data()); 397 } 398 } 399 break; 400 401 case EIB_MC_AUTHORIZE: 402 if (c->size < 6) 403 { 404 c->sendreject (); 405 break; 406 } 407 EIBSETTYPE (buf, EIB_MC_AUTHORIZE); 408 key = 409 (c->buf[2] << 24) | (c->buf[3] << 16) | (c->buf[4] << 8) | 410 (c->buf[5]); 411 if (m.A_Authorize (key, buf[2]) == -1) 412 c->sendreject (); 413 else 414 c->sendmessage (3, buf); 415 break; 416 417 case EIB_MC_KEY_WRITE: 418 if (c->size < 7) 419 { 420 c->sendreject (); 421 break; 422 } 423 key = 424 (c->buf[2] << 24) | (c->buf[3] << 16) | (c->buf[4] << 8) | 425 (c->buf[5]); 426 if (m.A_KeyWrite (key, *(c->buf + 6)) == -1) 427 c->sendreject (); 428 else 429 c->sendreject (EIB_MC_KEY_WRITE); 430 break; 431 432 case EIB_MC_PROP_DESC: 433 if (c->size < 4) 434 { 435 c->sendreject (); 436 break; 437 } 438 if (m.A_Property_Desc (c->buf[2], c->buf[3], 0, buf[2], maskver, 439 buf[5]) == -1) 440 c->sendreject (); 441 else 442 { 443 EIBSETTYPE (buf, EIB_MC_PROP_DESC); 444 buf[3] = (maskver >> 8) & 0xff; 445 buf[4] = (maskver) & 0xff; 446 c->sendmessage (6, buf); 447 } 448 break; 449 450 case EIB_MC_PROP_SCAN: 451 { 452 std::vector < PropertyInfo > p; 453 if (m.X_PropertyScan (p) == -1) 454 c->sendreject (); 455 else 456 { 457 CArray erg; 458 erg.resize (2 + p.size() * 6); 459 EIBSETTYPE (erg, EIB_MC_PROP_SCAN); 460 unsigned int ii = 0; 461 ITER( i,p) 462 { 463 erg[ii + 2] = i->obj; 464 erg[ii + 3] = i->property; 465 erg[ii + 4] = i->type; 466 erg[ii + 5] = (i->count >> 8) & 0xff; 467 erg[ii + 6] = (i->count) & 0xff; 468 erg[ii + 7] = i->access; 469 ii += 6; 470 } 471 c->sendmessage (erg.size(), erg.data()); 472 } 473 } 474 break; 475 476 case EIB_RESET_CONNECTION: 477 i = -1; 478 break; 479 480 case EIB_MC_RESTART: 481 m.A_Restart (); 482 c->sendreject (EIB_MC_RESTART); 483 break; 484 485 case EIB_MC_WRITE_NOVERIFY: 486 if (c->size < 6) 487 { 488 c->sendreject (); 489 break; 490 } 491 { 492 memaddr_t addr = (c->buf[2] << 8) | (c->buf[3]); 493 unsigned len = (c->buf[4] << 8) | (c->buf[5]); 494 if (c->size < len + 6) 495 { 496 c->sendreject (); 497 break; 498 } 499 i = m.A_Memory_Write_Block (addr, CArray (c->buf + 6, len)); 500 if (i != 0) 501 c->sendreject (EIB_PROCESSING_ERROR); 502 else 503 c->sendreject (EIB_MC_WRITE_NOVERIFY); 504 } 505 break; 506 507 default: 508 c->sendreject (); 509 } 510 } 511 while (i != -1); 512 } 513 514 void 515 ManagementIndividual (ClientConnPtr c, uint8_t *buf, size_t len) 516 { 517 eibaddr_t dest; 518 int i; 519 520 if (c->size < 4) 521 { 522 c->sendreject (); 523 return; 524 } 525 526 dest = (c->buf[2] << 8) | (c->buf[3]); 527 Management_Individual m (c->t, dest); 528 if (!m.init (c->l3)) 529 { 530 c->sendreject (EIB_PROCESSING_ERROR); 531 return; 532 } 533 c->sendreject (EIB_MC_INDIVIDUAL); 534 do 535 { 536 i = c->readmessage (); 537 if (i != -1) 538 switch (EIBTYPE (c->buf)) 539 { 540 case EIB_MC_PROP_READ: 541 if (c->size < 7) 542 { 543 c->sendreject (); 544 break; 545 } 546 { 547 CArray data, erg; 548 if (m.A_Property_Read (c->buf[2], c->buf[3], 549 (c->buf[4] << 8) | c->buf[5], c->buf[6], 550 data) == -1) 551 c->sendreject (); 552 else 553 { 554 erg.resize (2); 555 EIBSETTYPE (erg, EIB_MC_PROP_READ); 556 erg.setpart (data, 2); 557 c->sendmessage (erg.size(), erg.data()); 558 } 559 } 560 break; 561 562 case EIB_MC_PROP_WRITE: 563 if (c->size < 7) 564 { 565 c->sendreject (); 566 break; 567 } 568 { 569 CArray data, erg; 570 if (m.A_Property_Write (c->buf[2], c->buf[3], 571 (c->buf[4] << 8) | c->buf[5], c->buf[6], 572 CArray (c->buf + 7, c->size - 7), 573 erg) == -1) 574 c->sendreject (); 575 else 576 { 577 erg.resize (2); 578 EIBSETTYPE (erg, EIB_MC_PROP_WRITE); 579 erg.setpart (data, 2); 580 c->sendmessage (erg.size(), erg.data()); 581 } 582 } 583 break; 584 585 case EIB_RESET_CONNECTION: 586 i = -1; 587 break; 588 589 default: 590 c->sendreject (); 591 } 592 } 593 while (i != -1); 594 } 595 596 void 597 LoadImage (ClientConnPtr c, uint8_t *buf, size_t len) 598 { 599 uint8_t buf[200]; 600 CArray img (c->buf + 2, c->size - 2); 601 CArray erg; 602 unsigned int j; 603 BCUImage *i; 604 BCU_LOAD_RESULT r = PrepareLoadImage (img, i); 605 if (r != IMG_IMAGE_LOADABLE) 606 { 607 if (i) 608 delete i; 609 EIBSETTYPE (buf, EIB_LOAD_IMAGE); 610 buf[2] = (r >> 8) & 0xff; 611 buf[3] = (r) & 0xff; 612 c->sendmessage (4, buf); 613 return; 614 } 615 { 616 uint16_t maskver; 617 uint8_t ch; 618 r = IMG_NO_DEVICE_CONNECTION; 619 Management_Connection m = Management_Connection (c->t, i->addr); 620 if (!m.init (c->l3)) 621 goto out; 622 r = IMG_MASK_READ_FAILED; 623 if (m.A_Device_Descriptor_Read (maskver) == -1) 624 goto out; 625 r = IMG_WRONG_MASK_VERSION; 626 if (i->BCUType == BCUImage::B_bcu1) 627 { 628 if (maskver != 0x0012) 629 goto out; 630 631 /* set error flags in BCU (0x10D = 0x00) */ 632 r = IMG_CLEAR_ERROR; 633 ch = 0; 634 if (m.X_Memory_Write_Block (0x010d, CArray (&ch, 1)) != 0) 635 goto out; 636 637 /*set length of the address tab to 1 */ 638 r = IMG_RESET_ADDR_TAB; 639 ch = 0x01; 640 if (m.X_Memory_Write_Block (0x0116, CArray (&ch, 1)) != 0) 641 goto out; 642 643 /*load the data from 0x100 to 0x100 */ 644 r = IMG_LOAD_HEADER; 645 ch = 0xff; 646 if (m.X_Memory_Write_Block (0x0100, CArray (&ch, 1)) != 0) 647 goto out; 648 649 /*load the data from 0x103 to 0x10C */ 650 if (m.X_Memory_Write_Block (0x0103, 651 CArray (i->code.data() + 0x03, 652 10)) != 0) 653 goto out; 654 655 /*load the data from 0x10E to 0x115 */ 656 if (m.X_Memory_Write_Block (0x010E, 657 CArray (i->code.data() + 0x0E, 8)) != 0) 658 goto out; 659 660 /*load the data from 0x119H to eeprom end */ 661 r = IMG_LOAD_MAIN; 662 if (m.X_Memory_Write_Block (0x119, 663 CArray (i->code.data() + 0x19, 664 i->code.size() - 0x19)) != 0) 665 goto out; 666 667 if (m.X_Memory_Write_Block (0x0100, CArray (i->code.data(), 1)) != 668 0) 669 goto out; 670 671 /*erase the user RAM (0x0CE to 0x0DF) */ 672 r = IMG_ZERO_RAM; 673 uint8_t zero[18] = { 0 }; 674 if (m.X_Memory_Write_Block (0x00ce, CArray (zero, 18)) != 0) 675 goto out; 676 677 /* set the length of the address table */ 678 r = IMG_FINALIZE_ADDR_TAB; 679 if (m.X_Memory_Write_Block (0x0116, 680 CArray (i->code.data() + 0x16, 1)) != 0) 681 goto out; 682 683 /* reset all error flags in the BCU (0x10D = 0xFF) */ 684 r = IMG_PREPARE_RUN; 685 ch = 0xff; 686 if (m.X_Memory_Write_Block (0x010d, CArray (&ch, 1)) != 0) 687 goto out; 688 689 r = IMG_RESTART; 690 m.A_Restart (); 691 692 r = IMG_LOADED; 693 goto out; 694 } 695 if (i->BCUType == BCUImage::B_bcu20 || i->BCUType == BCUImage::B_bcu21) 696 { 697 if (maskver != 0x0020 && i->BCUType == BCUImage::B_bcu20) 698 goto out; 699 700 if (maskver != 0x0021 && i->BCUType == BCUImage::B_bcu21) 701 goto out; 702 703 uint8_t level; 704 r = IMG_AUTHORIZATION_FAILED; 705 if (m.A_Authorize (i->installkey, level) == -1) 706 goto out; 707 708 if (level) 709 goto out; 710 711 r = IMG_KEY_WRITE; 712 for (j = 0; j < 3; j++) 713 { 714 level = j; 715 if (m.A_KeyWrite (i->keys[level], level) == -1) 716 goto out; 717 if (j != level) 718 goto out; 719 } 720 721 ITER (j, i->load) 722 { 723 r = j->error; 724 if (j->obj != 0xff) 725 { 726 if (m.A_Property_Write (j->obj, j->prop, 727 j->start, 1, j->req, 728 erg) == -1) 729 goto out; 730 if (erg != j->result) 731 goto out; 732 } 733 if (j->memaddr != 0xffff) 734 if (m.X_Memory_Write_Block (j->memaddr, 735 CArray (i->code.data() + 736 j->memaddr - 0x100, 737 j->len)) != 0) 738 goto out; 739 } 740 741 r = IMG_RESTART; 742 m.A_Restart (); 743 744 r = IMG_LOADED; 745 goto out; 746 } 747 } 748 out: 749 750 if (i) 751 delete i; 752 EIBSETTYPE (buf, EIB_LOAD_IMAGE); 753 buf[2] = (r >> 8) & 0xff; 754 buf[3] = (r) & 0xff; 755 c->sendmessage (4, buf); 756 } 757