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