1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * M-Systems Block Device Driver for 5 * Binary Partition region of DiskOnChip (TM) Devices 6 * File: dev_msys.c 7 * 8 * To create a binary partition, we use the M-Systems Linux utility 9 * "dformat" for low-level (INFTL/NFTL) format the device for a 10 * BDTL (Block Device translation Layer) Partition as well as a 11 * user-defined binary partition of various sizes. Hereis an 12 * example of creating a device with a name of BIPO of size 1M with 13 * initial 800K kernel data image file vmlinux.img 14 * 15 * dformat -win:1f006000 -bdkL0:1M -bdkN0:BIPO -bdkF0:vmlinux.img 16 * 17 * Notes: 18 * 19 * 1) DFORMAT must be run AT LEAST ONCE, in order to create the 20 * binary partition area. Note also that the filename must be 21 * provided to write the binary partition. 22 * 23 * 2) All kernel image files must be 32K page aligned! 24 * To workaround DiskOnChip (TM) binary partition loader page 25 * write issue. In order for DOC to compute ECC/EDC, you need 26 * to always write a page (32K) of data (minimum). If the 27 * image is not page aligned, we simply write N bytes of zeros 28 * at the end so that the DOC ASIC controller will correctly 29 * compute the ECC syndrome bytes and all will be good. 30 * See mkflashimage for more details. 31 * 32 * 3) Note that the CFE loader will never read these bytes, 33 * we just put them there to keep the DOC asic controller happy. 34 * 35 * Author: Mitch Lichtenberg (mpl@broadcom.com) 36 * Author: James Dougherty (jfd@broadcom.com) 37 * 38 ********************************************************************* 39 * 40 * Copyright 2000,2001 41 * Broadcom Corporation. All rights reserved. 42 * 43 * This software is furnished under license and may be used and 44 * copied only in accordance with the following terms and 45 * conditions. Subject to these conditions, you may download, 46 * copy, install, use, modify and distribute modified or unmodified 47 * copies of this software in source and/or binary form. No title 48 * or ownership is transferred hereby. 49 * 50 * 1) Any source code used, modified or distributed must reproduce 51 * and retain this copyright notice and list of conditions as 52 * they appear in the source file. 53 * 54 * 2) No right is granted to use any trade name, trademark, or 55 * logo of Broadcom Corporation. Neither the "Broadcom 56 * Corporation" name nor any trademark or logo of Broadcom 57 * Corporation may be used to endorse or promote products 58 * derived from this software without the prior written 59 * permission of Broadcom Corporation. 60 * 61 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 62 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 63 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 64 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 65 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 66 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 67 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 69 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 70 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 71 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 72 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 73 * THE POSSIBILITY OF SUCH DAMAGE. 74 ********************************************************************* */ 75 76#include "cfe.h" 77 78#include "dev_msys.h" 79#include "dev_flash.h" 80#include "dev_newflash.h" 81 82/* ********************************************************************* 83 * Forward declarations 84 ********************************************************************* */ 85static FLStatus bdkdrv_print_status(const FLStatus bStat); 86 87 88static void bdkdrv_probe(cfe_driver_t *drv, 89 unsigned long probe_a, unsigned long probe_b, 90 void *probe_ptr); 91 92static int bdkdrv_open(cfe_devctx_t *ctx); 93static int bdkdrv_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 94static int bdkdrv_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat); 95static int bdkdrv_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 96static int bdkdrv_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 97static int bdkdrv_close(cfe_devctx_t *ctx); 98 99/* ********************************************************************* 100 * Device dispatch 101 ********************************************************************* */ 102 103const static cfe_devdisp_t bdkdrv_dispatch = { 104 bdkdrv_open, 105 bdkdrv_read, 106 bdkdrv_inpstat, 107 bdkdrv_write, 108 bdkdrv_ioctl, 109 bdkdrv_close, 110 NULL, 111 NULL 112}; 113 114const cfe_driver_t bdkdrv = { 115 "M-Systems Binary Partition", 116 "doc", 117 CFE_DEV_OTHER, 118 &bdkdrv_dispatch, 119 bdkdrv_probe 120}; 121 122typedef struct bdkdrv_s { 123 newflash_probe_t bdkdrv_probe; /* data from probe */ 124 flash_info_t bdkdrv_info; /* data from flash info */ 125 int bdkdrv_devsize; /* size reported by driver */ 126 int bdkdrv_initialized; /* true if we've probed already */ 127 int bdkdrv_unlocked; 128 FLStatus status; 129 unsigned long base, size; 130 unsigned char sign[SIGNATURE_LEN] ; 131 unsigned long real_part_size ; 132 unsigned long image_size ; 133 unsigned long unit_size ; 134 unsigned long start_unit; 135 unsigned long num_blocks; 136 unsigned char chksum; 137} bdkdrv_t; 138 139 140/* 141 * Output message for FLStatus from M-Systems BDK software. 142 */ 143FLStatus 144bdkdrv_print_status(const FLStatus bStat) 145{ 146 printf("Error: FLStatus - ") ; 147 148 switch(bStat){ 149 150 case flOK: 151 printf("OK\n") ; 152 break ; 153 case flBadFunction: 154 printf("BadFunction\n") ; 155 break ; 156 case flFileNotFound: 157 printf("FileNotFound\n") ; 158 break ; 159 case flPathNotFound: 160 printf("PathNotFound\n") ; 161 break ; 162 case flTooManyOpenFiles: 163 printf("TooManyOpenFiles\n") ; 164 break ; 165 case flNoWriteAccess: 166 printf("NoWriteAccess\n") ; 167 break ; 168 case flBadFileHandle: 169 printf("BadFileHandle\n") ; 170 break ; 171 case flDriveNotAvailable: 172 printf("DriveNotAvailable\n") ; 173 break ; 174 case flNonFATformat: 175 printf("NonFATformat\n") ; 176 break ; 177 case flFormatNotSupported: 178 printf("FormatNotSupported\n") ; 179 break ; 180 case flNoMoreFiles: 181 printf("NoMoreFiles\n") ; 182 break ; 183 case flWriteProtect: 184 printf("WriteProtect\n") ; 185 break ; 186 case flBadDriveHandle: 187 printf("BadDriveHandle\n") ; 188 break ; 189 case flDriveNotReady: 190 printf("DriveNotReady\n") ; 191 break ; 192 case flUnknownCmd: 193 printf("UnknownCmd\n") ; 194 break ; 195 case flBadFormat: 196 printf("BadFormat\n") ; 197 break ; 198 case flBadLength: 199 printf("BadLength\n") ; 200 break ; 201 case flDataError: 202 printf("DataError\n") ; 203 break ; 204 case flUnknownMedia: 205 printf("UnknownMedia\n") ; 206 break ; 207 case flSectorNotFound: 208 printf("SectorNotFound\n") ; 209 break ; 210 case flOutOfPaper: 211 printf("OutOfPaper\n") ; 212 break ; 213 case flWriteFault: 214 printf("WriteFault\n") ; 215 break ; 216 case flReadFault: 217 printf("ReadFault\n") ; 218 break ; 219 case flGeneralFailure: 220 printf("GeneralFailure\n") ; 221 break ; 222 case flDiskChange: 223 printf("DiskChange\n") ; 224 break ; 225 case flVppFailure: 226 printf("VppFailure\n") ; 227 break ; 228 case flBadParameter: 229 printf("BadParameter\n") ; 230 break ; 231 case flNoSpaceInVolume: 232 printf("NoSpaceInVolume\n") ; 233 break ; 234 case flInvalidFATchain: 235 printf("InvalidFATchain\n") ; 236 break ; 237 case flRootDirectoryFull: 238 printf("RootDirectoryFull\n") ; 239 break ; 240 case flNotMounted: 241 printf("NotMounted\n") ; 242 break ; 243 case flPathIsRootDirectory: 244 printf("PathIsRootDirectory\n") ; 245 break ; 246 case flNotADirectory: 247 printf("NotADirectory\n") ; 248 break ; 249 case flDirectoryNotEmpty: 250 printf("DirectoryNotEmpty\n") ; 251 break ; 252 case flFileIsADirectory: 253 printf("FileIsADirectory\n") ; 254 break ; 255 case flAdapterNotFound: 256 printf("AdapterNotFound\n") ; 257 break ; 258 case flFormattingError: 259 printf("FormattingError\n") ; 260 break ; 261 case flNotEnoughMemory: 262 printf("NotEnoughMemory\n") ; 263 break ; 264 case flVolumeTooSmall: 265 printf("VolumeTooSmall\n") ; 266 break ; 267 case flBufferingError: 268 printf("BufferingError\n") ; 269 break ; 270 case flFileAlreadyExists: 271 printf("FileAlreadyExists\n") ; 272 break ; 273 case flIncomplete: 274 printf("Incomplete\n") ; 275 break ; 276 case flTimedOut: 277 printf("TimedOut\n") ; 278 break ; 279 case flTooManyComponents: 280 printf("TooManyComponents\n") ; 281 break ; 282 case flTooManyDrives: 283 printf("TooManyDrives\n") ; 284 break ; 285 case flTooManyBinaryPartitions: 286 printf("TooManyBinaryPartitions\n") ; 287 break ; 288 case flPartitionNotFound: 289 printf("PartitionNotFound\n") ; 290 break ; 291 case flFeatureNotSupported: 292 printf("FeatureNotSupported\n") ; 293 break ; 294 case flWrongVersion: 295 printf("WrongVersion\n") ; 296 break ; 297 case flTooManyBadBlocks: 298 printf("TooManyBadBlocks\n") ; 299 break ; 300 case flNotProtected: 301 printf("NotProtected\n") ; 302 break ; 303 case flUnchangeableProtection: 304 printf("UnchangableProection\n") ; 305 break ; 306 case flBadBBT: 307 printf("BadBBT\n") ; 308 break ; 309 case flInterleaveError: 310 printf("InterlreavError\n") ; 311 break ; 312 case flWrongKey: 313 printf("WrongKey\n") ; 314 break ; 315 case flHWProtection: 316 printf("HWProtection\n") ; 317 break ; 318 case flBadDownload: 319 printf("BadDownload\n") ; 320 break ; 321 default: 322 printf("Unknown status\n") ; 323 break ; 324 } 325 326 return (flOK) ; 327} 328 329 330/* ********************************************************************* 331 * bdkdrv_probe(drv,probe_a,probe_b,probe_ptr) 332 * 333 * Device probe routine. Attach the flash device to 334 * CFE's device table. 335 * 336 * Input parameters: 337 * drv - driver descriptor 338 * probe_a - physical address of flash 339 * probe_b - size of flash (bytes) 340 * probe_ptr - unused 341 * 342 * Return value: 343 * nothing 344 ********************************************************************* */ 345 346static void bdkdrv_probe(cfe_driver_t *drv, 347 unsigned long probe_a, unsigned long probe_b, 348 void *probe_ptr) 349{ 350 bdkdrv_t *softc; 351 char descr[80]; 352 newflash_probe_t *probe = (newflash_probe_t *) probe_ptr; 353 354 /* 355 * probe_a is the flash base address 356 * probe_b is the size of the flash 357 * probe_ptr is unused. 358 */ 359 360 softc = (bdkdrv_t *) KMALLOC(sizeof(bdkdrv_t),0); 361 if (softc) { 362 memset(softc,0,sizeof(bdkdrv_t)); 363 364 softc->base = probe_a; 365 softc->size = probe_b; 366 367 softc->bdkdrv_initialized = 0; 368 369 /* Init BDK API */ 370 bdkInit(); 371 372 /* Find devices, setup driver metadata state */ 373 softc->status = bdkFindDiskOnChip( &softc->base, &softc->size ); 374 375 if( softc->status != flOK ) { 376 printf("ERROR: DiskOnChip not found!\n"); 377 bdkdrv_print_status( softc->status ) ; 378 bdkExit(); 379 } 380 381 /* Get signature of device and check offset of binary partition */ 382 tffscpy((void *)softc->sign, 383 (void *)DEFAULTSIGNATURE,BDK_SIGNATURE_NAME); 384 softc->sign[BDK_SIGNATURE_NAME] = '\0'; 385 386 softc->bdkdrv_info.flash_type = FLASH_TYPE_FLASH; 387 softc->bdkdrv_info.flash_base = softc->base; 388 softc->bdkdrv_info.flash_size = softc->size; 389 softc->bdkdrv_info.flash_type = FLASH_TYPE_FLASH; 390 softc->bdkdrv_info.flash_flags = 0; 391 392 xsprintf(descr,"%s at %08X size %dMB", 393 drv->drv_description, 394 softc->base, 395 softc->size/(1024*1024)); 396 397 398 if (probe) { 399 /* 400 * Passed probe structure, do fancy stuff 401 */ 402 memcpy(&(softc->bdkdrv_probe),probe,sizeof(newflash_probe_t)); 403 if (softc->bdkdrv_probe.flash_nchips == 0) { 404 softc->bdkdrv_probe.flash_nchips = 1; 405 } 406 } 407 408 409 cfe_attach(drv,softc,NULL,descr); 410 } 411 412} 413 414 415/* ********************************************************************* 416 * bdkdrv_open(ctx) 417 * 418 * Called when the flash device is opened. 419 * 420 * Input parameters: 421 * ctx - device context 422 * 423 * Return value: 424 * 0 if ok else error code 425 ********************************************************************* */ 426 427static int bdkdrv_open(cfe_devctx_t *ctx) 428{ 429 bdkdrv_t *softc = ctx->dev_softc; 430 431 /* 432 * do initialization 433 */ 434 435 if (!softc->bdkdrv_initialized) { 436 /* Get Boot information */ 437 softc->start_unit = 0; 438 softc->status = bdkGetBootPartitionInfo( softc->start_unit, 439 &softc->real_part_size, 440 &softc->image_size, 441 &softc->unit_size, 442 softc->sign ); 443 if( softc->status != flOK ) { 444 printf("Partition with Sign: %s not found\n", softc->sign); 445 bdkdrv_print_status( softc->status ) ; 446 bdkExit(); 447 return -1; 448 } 449 printf("Partition: [%s], Size=%ld," 450 "UnitSize=%ld\n\t%ld Units,ImageSize=%d (%x)\n", 451 softc->sign, softc->real_part_size, 452 softc->unit_size, softc->real_part_size / softc->unit_size, 453 (int)softc->image_size, (int)softc->image_size); 454 455 softc->num_blocks = softc->real_part_size / softc->unit_size; 456 457 softc->bdkdrv_info.flash_size = softc->image_size; 458 softc->bdkdrv_info.flash_type = FLASH_TYPE_FLASH; 459 460#if 0 461 softc->bdkdrv_probe.flash_nsectors = 462 softc->image_size / softc->unit_size; 463#else 464 softc->bdkdrv_probe.flash_nsectors = softc->image_size; 465#endif 466 softc->bdkdrv_probe.flash_size = softc->image_size; 467 printf("nblocks=%d, nsectors=%d size=%d\n", 468 softc->num_blocks, softc->bdkdrv_probe.flash_nsectors, 469 softc->bdkdrv_probe.flash_size); 470 471 /* Chip Now Ready for I/O */ 472 softc->bdkdrv_initialized = TRUE; 473 } 474 475 return 0; 476} 477 478 479/* ********************************************************************* 480 * bdkdrv_read(ctx,buffer) 481 * 482 * Read data from the flash device. The flash device is 483 * considered to be like a disk (you need to specify the offset). 484 * 485 * Input parameters: 486 * ctx - device context 487 * buffer - buffer descriptor 488 * 489 * Return value: 490 * 0 if ok, else error code 491 ********************************************************************* */ 492 493static int bdkdrv_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 494{ 495 bdkdrv_t *softc = ctx->dev_softc; 496 unsigned char *bptr; 497#if 0 498 unsigned char *tmp; 499#endif 500 int offset; 501 int blen, ret, startUnit = 0; 502 503 bptr = buffer->buf_ptr; 504 blen = buffer->buf_length; 505 offset = (int) buffer->buf_offset; 506 507 if (!(softc->bdkdrv_unlocked)) { 508 if ((offset + blen) > softc->real_part_size) { 509 blen = softc->real_part_size - offset; 510 } 511 } 512 printf("bdkdrv_read: bptr=0x%x blen=%d offset=%d\n", 513 (unsigned)bptr, blen, offset); 514#if 0 515 tmp = (unsigned char*)KMALLOC(softc->unit_size,0); 516 517 startUnit = offset / softc->unit_size; /* e.g. 512/32K */ 518 519 ret = bdkCopyBootAreaInit( startUnit, 520 softc->image_size, softc->sign ); 521 522 /* Read data from binary partition */ 523 ret = bdkCopyBootAreaBlock((void*)tmp, 524 blen, 525 &softc->chksum); 526 527 memcpy(bptr, tmp + offset, blen); 528 KFREE(tmp); 529#else 530 /* Read data from binary partition */ 531 ret = bdkCopyBootArea((void*)bptr, 532 startUnit, 533 softc->image_size, 534 &softc->chksum, 535 softc->sign); 536#endif 537 if ( ret == flOK ) { 538 printf("DOC read %d bytes OK with checksum 0x%x\n", 539 (int)blen, (int)softc->chksum); 540 } else { 541 bdkdrv_print_status( ret ); 542 return -1; 543 } 544 545 buffer->buf_retlen = blen; 546 547 return 0; 548} 549 550/* ********************************************************************* 551 * bdkdrv_inpstat(ctx,inpstat) 552 * 553 * Return "input status". For flash devices, we always return true. 554 * 555 * Input parameters: 556 * ctx - device context 557 * inpstat - input status structure 558 * 559 * Return value: 560 * 0 if ok, else error code 561 ********************************************************************* */ 562 563static int bdkdrv_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat) 564{ 565 /* bdkdrv_t *softc = ctx->dev_softc; */ 566 567 inpstat->inp_status = 1; 568 return 0; 569} 570 571 572 573 574/* ********************************************************************* 575 * bdkdrv_write(ctx,buffer) 576 * 577 * Write data to the flash device. The flash device is 578 * considered to be like a disk (you need to specify the offset). 579 * 580 * Input parameters: 581 * ctx - device context 582 * buffer - buffer descriptor 583 * 584 * Return value: 585 * 0 if ok, else error code 586 ********************************************************************* */ 587 588static int bdkdrv_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 589{ 590#if 0 591 bdkdrv_t *softc = ctx->dev_softc; 592 unsigned char *bptr; 593 int offset; 594 int blen; 595 int res; 596 597 bptr = buffer->buf_ptr; 598 blen = buffer->buf_length; 599 offset = (int) buffer->buf_offset; 600 601 if (!(softc->bdkdrv_unlocked)) { 602 if ((offset + blen) > softc->bdkdrv_devsize) { 603 blen = softc->bdkdrv_devsize - offset; 604 } 605 } 606 607 res = FLASHOP_WRITE_BLOCK(softc,offset,bptr,blen); 608 609 buffer->buf_retlen = res; 610 611 /* XXX flush the cache here? */ 612 613 return (res == blen) ? 0 : CFE_ERR_IOERR; 614#else 615 printf("bdkdrv_write:\n"); 616 return 0; 617#endif 618} 619 620/* ********************************************************************* 621 * bdkdrv_ioctl(ctx,buffer) 622 * 623 * Handle special IOCTL functions for the flash. Flash devices 624 * support NVRAM information, sector and chip erase, and a 625 * special IOCTL for updating the running copy of CFE. 626 * 627 * Input parameters: 628 * ctx - device context 629 * buffer - descriptor for IOCTL parameters 630 * 631 * Return value: 632 * 0 if ok else error 633 ********************************************************************* */ 634static int bdkdrv_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 635{ 636 bdkdrv_t *softc = ctx->dev_softc; 637 /* 638 * If using flash to store environment, only the last sector 639 * is used for environment stuff. 640 */ 641 printf("bdkdrv_ioctl: command=%d\n", 642 (int)buffer->buf_ioctlcmd); 643 switch ((int)buffer->buf_ioctlcmd) { 644 645 case IOCTL_NVRAM_ERASE: 646 return CFE_ERR_UNSUPPORTED; 647 648 case IOCTL_NVRAM_GETINFO: 649 return CFE_ERR_UNSUPPORTED; 650 651 case IOCTL_FLASH_ERASE_SECTOR: 652 return 0; 653 654 case IOCTL_FLASH_ERASE_ALL: 655 return CFE_ERR_UNSUPPORTED; 656 657 case IOCTL_FLASH_WRITE_ALL: 658 return CFE_ERR_UNSUPPORTED; 659 660 case IOCTL_FLASH_GETINFO: 661 printf("bdkdrv_ioctl: getflashinfo:size=%d\n", 662 softc->bdkdrv_info.flash_size); 663 memcpy(buffer->buf_ptr,&(softc->bdkdrv_info),sizeof(flash_info_t)); 664 return 0; 665 666 case IOCTL_FLASH_GETSECTORS: 667 printf("bdkdrv_ioctl: nsectors=%d\n", 668 softc->bdkdrv_probe.flash_nsectors); 669 670 return softc->bdkdrv_probe.flash_nsectors; 671 672 case IOCTL_FLASH_ERASE_RANGE: 673 return 0; 674 675 case IOCTL_NVRAM_UNLOCK: 676 softc->bdkdrv_unlocked = TRUE; 677 break; 678 679 default: 680 return CFE_ERR_UNSUPPORTED; 681 } 682 683 return CFE_ERR_UNSUPPORTED; 684} 685 686 687/* ********************************************************************* 688 * bdkdrv_close(ctx) 689 * 690 * Close the flash device. 691 * 692 * Input parameters: 693 * ctx - device context 694 * 695 * Return value: 696 * 0 697 ********************************************************************* */ 698static int bdkdrv_close(cfe_devctx_t *ctx) 699{ 700 /* bdkdrv_t *softc = ctx->dev_softc; */ 701 702 /* XXX Invalidate the cache */ 703 return 0; 704} 705 706 707