12e192b24SSimon Glass /* 22e192b24SSimon Glass * (C) Copyright 2000-2011 32e192b24SSimon Glass * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 42e192b24SSimon Glass * 52e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 62e192b24SSimon Glass */ 72e192b24SSimon Glass #include <common.h> 82e192b24SSimon Glass #include <command.h> 92e192b24SSimon Glass #include <part.h> 102e192b24SSimon Glass 112e192b24SSimon Glass #if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_SCSI) || \ 122e192b24SSimon Glass defined(CONFIG_USB_STORAGE) 132e192b24SSimon Glass int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc, 142e192b24SSimon Glass char *const argv[]) 152e192b24SSimon Glass { 162e192b24SSimon Glass int dev, part; 172e192b24SSimon Glass ulong addr = CONFIG_SYS_LOAD_ADDR; 182e192b24SSimon Glass ulong cnt; 192e192b24SSimon Glass disk_partition_t info; 202e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 212e192b24SSimon Glass image_header_t *hdr; 222e192b24SSimon Glass #endif 234101f687SSimon Glass struct blk_desc *dev_desc; 242e192b24SSimon Glass 252e192b24SSimon Glass #if defined(CONFIG_FIT) 262e192b24SSimon Glass const void *fit_hdr = NULL; 272e192b24SSimon Glass #endif 282e192b24SSimon Glass 292e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_START); 302e192b24SSimon Glass if (argc > 3) { 312e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_ADDR); 322e192b24SSimon Glass return CMD_RET_USAGE; 332e192b24SSimon Glass } 342e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_ADDR); 352e192b24SSimon Glass 362e192b24SSimon Glass if (argc > 1) 372e192b24SSimon Glass addr = simple_strtoul(argv[1], NULL, 16); 382e192b24SSimon Glass 392e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_BOOT_DEVICE); 402e192b24SSimon Glass 41e35929e4SSimon Glass part = blk_get_device_part_str(intf, (argc == 3) ? argv[2] : NULL, 422e192b24SSimon Glass &dev_desc, &info, 1); 432e192b24SSimon Glass if (part < 0) { 442e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_TYPE); 452e192b24SSimon Glass return 1; 462e192b24SSimon Glass } 472e192b24SSimon Glass 48*bcce53d0SSimon Glass dev = dev_desc->devnum; 492e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_TYPE); 502e192b24SSimon Glass 512e192b24SSimon Glass printf("\nLoading from %s device %d, partition %d: " 522e192b24SSimon Glass "Name: %.32s Type: %.32s\n", intf, dev, part, info.name, 532e192b24SSimon Glass info.type); 542e192b24SSimon Glass 552e192b24SSimon Glass debug("First Block: " LBAFU ", # of blocks: " LBAFU 562e192b24SSimon Glass ", Block Size: %ld\n", 572e192b24SSimon Glass info.start, info.size, info.blksz); 582e192b24SSimon Glass 592e192b24SSimon Glass if (dev_desc->block_read(dev_desc, info.start, 1, (ulong *)addr) != 1) { 602e192b24SSimon Glass printf("** Read error on %d:%d\n", dev, part); 612e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_PART_READ); 622e192b24SSimon Glass return 1; 632e192b24SSimon Glass } 642e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_PART_READ); 652e192b24SSimon Glass 662e192b24SSimon Glass switch (genimg_get_format((void *) addr)) { 672e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 682e192b24SSimon Glass case IMAGE_FORMAT_LEGACY: 692e192b24SSimon Glass hdr = (image_header_t *) addr; 702e192b24SSimon Glass 712e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_FORMAT); 722e192b24SSimon Glass 732e192b24SSimon Glass if (!image_check_hcrc(hdr)) { 742e192b24SSimon Glass puts("\n** Bad Header Checksum **\n"); 752e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_CHECKSUM); 762e192b24SSimon Glass return 1; 772e192b24SSimon Glass } 782e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_CHECKSUM); 792e192b24SSimon Glass 802e192b24SSimon Glass image_print_contents(hdr); 812e192b24SSimon Glass 822e192b24SSimon Glass cnt = image_get_image_size(hdr); 832e192b24SSimon Glass break; 842e192b24SSimon Glass #endif 852e192b24SSimon Glass #if defined(CONFIG_FIT) 862e192b24SSimon Glass case IMAGE_FORMAT_FIT: 872e192b24SSimon Glass fit_hdr = (const void *) addr; 882e192b24SSimon Glass puts("Fit image detected...\n"); 892e192b24SSimon Glass 902e192b24SSimon Glass cnt = fit_get_size(fit_hdr); 912e192b24SSimon Glass break; 922e192b24SSimon Glass #endif 932e192b24SSimon Glass default: 942e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_FORMAT); 952e192b24SSimon Glass puts("** Unknown image type\n"); 962e192b24SSimon Glass return 1; 972e192b24SSimon Glass } 982e192b24SSimon Glass 992e192b24SSimon Glass cnt += info.blksz - 1; 1002e192b24SSimon Glass cnt /= info.blksz; 1012e192b24SSimon Glass cnt -= 1; 1022e192b24SSimon Glass 1032e192b24SSimon Glass if (dev_desc->block_read(dev_desc, info.start + 1, cnt, 1042e192b24SSimon Glass (ulong *)(addr + info.blksz)) != cnt) { 1052e192b24SSimon Glass printf("** Read error on %d:%d\n", dev, part); 1062e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_READ); 1072e192b24SSimon Glass return 1; 1082e192b24SSimon Glass } 1092e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_READ); 1102e192b24SSimon Glass 1112e192b24SSimon Glass #if defined(CONFIG_FIT) 1122e192b24SSimon Glass /* This cannot be done earlier, 1132e192b24SSimon Glass * we need complete FIT image in RAM first */ 1142e192b24SSimon Glass if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) { 1152e192b24SSimon Glass if (!fit_check_format(fit_hdr)) { 1162e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ); 1172e192b24SSimon Glass puts("** Bad FIT image format\n"); 1182e192b24SSimon Glass return 1; 1192e192b24SSimon Glass } 1202e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK); 1212e192b24SSimon Glass fit_print_contents(fit_hdr); 1222e192b24SSimon Glass } 1232e192b24SSimon Glass #endif 1242e192b24SSimon Glass 1252e192b24SSimon Glass flush_cache(addr, (cnt+1)*info.blksz); 1262e192b24SSimon Glass 1272e192b24SSimon Glass /* Loading ok, update default load address */ 1282e192b24SSimon Glass load_addr = addr; 1292e192b24SSimon Glass 1302e192b24SSimon Glass return bootm_maybe_autostart(cmdtp, argv[0]); 1312e192b24SSimon Glass } 1322e192b24SSimon Glass #endif 133