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 11c649e3c9SSimon Glass #if defined(CONFIG_CMD_IDE) || defined(CONFIG_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 { 16*04681cb3SMarek Vasut __maybe_unused int dev; 17*04681cb3SMarek Vasut int part; 182e192b24SSimon Glass ulong addr = CONFIG_SYS_LOAD_ADDR; 192e192b24SSimon Glass ulong cnt; 202e192b24SSimon Glass disk_partition_t info; 212e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 222e192b24SSimon Glass image_header_t *hdr; 232e192b24SSimon Glass #endif 244101f687SSimon Glass struct blk_desc *dev_desc; 252e192b24SSimon Glass 2673223f0eSSimon Glass #if CONFIG_IS_ENABLED(FIT) 272e192b24SSimon Glass const void *fit_hdr = NULL; 282e192b24SSimon Glass #endif 292e192b24SSimon Glass 302e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_START); 312e192b24SSimon Glass if (argc > 3) { 322e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_ADDR); 332e192b24SSimon Glass return CMD_RET_USAGE; 342e192b24SSimon Glass } 352e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_ADDR); 362e192b24SSimon Glass 372e192b24SSimon Glass if (argc > 1) 382e192b24SSimon Glass addr = simple_strtoul(argv[1], NULL, 16); 392e192b24SSimon Glass 402e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_BOOT_DEVICE); 412e192b24SSimon Glass 42e35929e4SSimon Glass part = blk_get_device_part_str(intf, (argc == 3) ? argv[2] : NULL, 432e192b24SSimon Glass &dev_desc, &info, 1); 442e192b24SSimon Glass if (part < 0) { 452e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_TYPE); 462e192b24SSimon Glass return 1; 472e192b24SSimon Glass } 482e192b24SSimon Glass 49bcce53d0SSimon Glass dev = dev_desc->devnum; 502e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_TYPE); 512e192b24SSimon Glass 522e192b24SSimon Glass printf("\nLoading from %s device %d, partition %d: " 532e192b24SSimon Glass "Name: %.32s Type: %.32s\n", intf, dev, part, info.name, 542e192b24SSimon Glass info.type); 552e192b24SSimon Glass 562e192b24SSimon Glass debug("First Block: " LBAFU ", # of blocks: " LBAFU 572e192b24SSimon Glass ", Block Size: %ld\n", 582e192b24SSimon Glass info.start, info.size, info.blksz); 592e192b24SSimon Glass 602a981dc2SSimon Glass if (blk_dread(dev_desc, info.start, 1, (ulong *)addr) != 1) { 612e192b24SSimon Glass printf("** Read error on %d:%d\n", dev, part); 622e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_PART_READ); 632e192b24SSimon Glass return 1; 642e192b24SSimon Glass } 652e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_PART_READ); 662e192b24SSimon Glass 672e192b24SSimon Glass switch (genimg_get_format((void *) addr)) { 682e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 692e192b24SSimon Glass case IMAGE_FORMAT_LEGACY: 702e192b24SSimon Glass hdr = (image_header_t *) addr; 712e192b24SSimon Glass 722e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_FORMAT); 732e192b24SSimon Glass 742e192b24SSimon Glass if (!image_check_hcrc(hdr)) { 752e192b24SSimon Glass puts("\n** Bad Header Checksum **\n"); 762e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_CHECKSUM); 772e192b24SSimon Glass return 1; 782e192b24SSimon Glass } 792e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_CHECKSUM); 802e192b24SSimon Glass 812e192b24SSimon Glass image_print_contents(hdr); 822e192b24SSimon Glass 832e192b24SSimon Glass cnt = image_get_image_size(hdr); 842e192b24SSimon Glass break; 852e192b24SSimon Glass #endif 8673223f0eSSimon Glass #if CONFIG_IS_ENABLED(FIT) 872e192b24SSimon Glass case IMAGE_FORMAT_FIT: 882e192b24SSimon Glass fit_hdr = (const void *) addr; 892e192b24SSimon Glass puts("Fit image detected...\n"); 902e192b24SSimon Glass 912e192b24SSimon Glass cnt = fit_get_size(fit_hdr); 922e192b24SSimon Glass break; 932e192b24SSimon Glass #endif 942e192b24SSimon Glass default: 952e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_FORMAT); 962e192b24SSimon Glass puts("** Unknown image type\n"); 972e192b24SSimon Glass return 1; 982e192b24SSimon Glass } 992e192b24SSimon Glass 1002e192b24SSimon Glass cnt += info.blksz - 1; 1012e192b24SSimon Glass cnt /= info.blksz; 1022e192b24SSimon Glass cnt -= 1; 1032e192b24SSimon Glass 1042a981dc2SSimon Glass if (blk_dread(dev_desc, info.start + 1, cnt, 1052e192b24SSimon Glass (ulong *)(addr + info.blksz)) != cnt) { 1062e192b24SSimon Glass printf("** Read error on %d:%d\n", dev, part); 1072e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_READ); 1082e192b24SSimon Glass return 1; 1092e192b24SSimon Glass } 1102e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_READ); 1112e192b24SSimon Glass 11273223f0eSSimon Glass #if CONFIG_IS_ENABLED(FIT) 1132e192b24SSimon Glass /* This cannot be done earlier, 1142e192b24SSimon Glass * we need complete FIT image in RAM first */ 1152e192b24SSimon Glass if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) { 1162e192b24SSimon Glass if (!fit_check_format(fit_hdr)) { 1172e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ); 1182e192b24SSimon Glass puts("** Bad FIT image format\n"); 1192e192b24SSimon Glass return 1; 1202e192b24SSimon Glass } 1212e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK); 1222e192b24SSimon Glass fit_print_contents(fit_hdr); 1232e192b24SSimon Glass } 1242e192b24SSimon Glass #endif 1252e192b24SSimon Glass 1262e192b24SSimon Glass flush_cache(addr, (cnt+1)*info.blksz); 1272e192b24SSimon Glass 1282e192b24SSimon Glass /* Loading ok, update default load address */ 1292e192b24SSimon Glass load_addr = addr; 1302e192b24SSimon Glass 1312e192b24SSimon Glass return bootm_maybe_autostart(cmdtp, argv[0]); 1322e192b24SSimon Glass } 1332e192b24SSimon Glass #endif 134