1*2e192b24SSimon Glass /* 2*2e192b24SSimon Glass * (C) Copyright 2000-2011 3*2e192b24SSimon Glass * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4*2e192b24SSimon Glass * 5*2e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 6*2e192b24SSimon Glass */ 7*2e192b24SSimon Glass #include <common.h> 8*2e192b24SSimon Glass #include <command.h> 9*2e192b24SSimon Glass #include <part.h> 10*2e192b24SSimon Glass 11*2e192b24SSimon Glass #if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_SCSI) || \ 12*2e192b24SSimon Glass defined(CONFIG_USB_STORAGE) 13*2e192b24SSimon Glass int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc, 14*2e192b24SSimon Glass char *const argv[]) 15*2e192b24SSimon Glass { 16*2e192b24SSimon Glass int dev, part; 17*2e192b24SSimon Glass ulong addr = CONFIG_SYS_LOAD_ADDR; 18*2e192b24SSimon Glass ulong cnt; 19*2e192b24SSimon Glass disk_partition_t info; 20*2e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 21*2e192b24SSimon Glass image_header_t *hdr; 22*2e192b24SSimon Glass #endif 23*2e192b24SSimon Glass block_dev_desc_t *dev_desc; 24*2e192b24SSimon Glass 25*2e192b24SSimon Glass #if defined(CONFIG_FIT) 26*2e192b24SSimon Glass const void *fit_hdr = NULL; 27*2e192b24SSimon Glass #endif 28*2e192b24SSimon Glass 29*2e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_START); 30*2e192b24SSimon Glass if (argc > 3) { 31*2e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_ADDR); 32*2e192b24SSimon Glass return CMD_RET_USAGE; 33*2e192b24SSimon Glass } 34*2e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_ADDR); 35*2e192b24SSimon Glass 36*2e192b24SSimon Glass if (argc > 1) 37*2e192b24SSimon Glass addr = simple_strtoul(argv[1], NULL, 16); 38*2e192b24SSimon Glass 39*2e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_BOOT_DEVICE); 40*2e192b24SSimon Glass 41*2e192b24SSimon Glass part = get_device_and_partition(intf, (argc == 3) ? argv[2] : NULL, 42*2e192b24SSimon Glass &dev_desc, &info, 1); 43*2e192b24SSimon Glass if (part < 0) { 44*2e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_TYPE); 45*2e192b24SSimon Glass return 1; 46*2e192b24SSimon Glass } 47*2e192b24SSimon Glass 48*2e192b24SSimon Glass dev = dev_desc->dev; 49*2e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_TYPE); 50*2e192b24SSimon Glass 51*2e192b24SSimon Glass printf("\nLoading from %s device %d, partition %d: " 52*2e192b24SSimon Glass "Name: %.32s Type: %.32s\n", intf, dev, part, info.name, 53*2e192b24SSimon Glass info.type); 54*2e192b24SSimon Glass 55*2e192b24SSimon Glass debug("First Block: " LBAFU ", # of blocks: " LBAFU 56*2e192b24SSimon Glass ", Block Size: %ld\n", 57*2e192b24SSimon Glass info.start, info.size, info.blksz); 58*2e192b24SSimon Glass 59*2e192b24SSimon Glass if (dev_desc->block_read(dev_desc, info.start, 1, (ulong *)addr) != 1) { 60*2e192b24SSimon Glass printf("** Read error on %d:%d\n", dev, part); 61*2e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_PART_READ); 62*2e192b24SSimon Glass return 1; 63*2e192b24SSimon Glass } 64*2e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_PART_READ); 65*2e192b24SSimon Glass 66*2e192b24SSimon Glass switch (genimg_get_format((void *) addr)) { 67*2e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 68*2e192b24SSimon Glass case IMAGE_FORMAT_LEGACY: 69*2e192b24SSimon Glass hdr = (image_header_t *) addr; 70*2e192b24SSimon Glass 71*2e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_FORMAT); 72*2e192b24SSimon Glass 73*2e192b24SSimon Glass if (!image_check_hcrc(hdr)) { 74*2e192b24SSimon Glass puts("\n** Bad Header Checksum **\n"); 75*2e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_CHECKSUM); 76*2e192b24SSimon Glass return 1; 77*2e192b24SSimon Glass } 78*2e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_CHECKSUM); 79*2e192b24SSimon Glass 80*2e192b24SSimon Glass image_print_contents(hdr); 81*2e192b24SSimon Glass 82*2e192b24SSimon Glass cnt = image_get_image_size(hdr); 83*2e192b24SSimon Glass break; 84*2e192b24SSimon Glass #endif 85*2e192b24SSimon Glass #if defined(CONFIG_FIT) 86*2e192b24SSimon Glass case IMAGE_FORMAT_FIT: 87*2e192b24SSimon Glass fit_hdr = (const void *) addr; 88*2e192b24SSimon Glass puts("Fit image detected...\n"); 89*2e192b24SSimon Glass 90*2e192b24SSimon Glass cnt = fit_get_size(fit_hdr); 91*2e192b24SSimon Glass break; 92*2e192b24SSimon Glass #endif 93*2e192b24SSimon Glass default: 94*2e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_FORMAT); 95*2e192b24SSimon Glass puts("** Unknown image type\n"); 96*2e192b24SSimon Glass return 1; 97*2e192b24SSimon Glass } 98*2e192b24SSimon Glass 99*2e192b24SSimon Glass cnt += info.blksz - 1; 100*2e192b24SSimon Glass cnt /= info.blksz; 101*2e192b24SSimon Glass cnt -= 1; 102*2e192b24SSimon Glass 103*2e192b24SSimon Glass if (dev_desc->block_read(dev_desc, info.start + 1, cnt, 104*2e192b24SSimon Glass (ulong *)(addr + info.blksz)) != cnt) { 105*2e192b24SSimon Glass printf("** Read error on %d:%d\n", dev, part); 106*2e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_READ); 107*2e192b24SSimon Glass return 1; 108*2e192b24SSimon Glass } 109*2e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_READ); 110*2e192b24SSimon Glass 111*2e192b24SSimon Glass #if defined(CONFIG_FIT) 112*2e192b24SSimon Glass /* This cannot be done earlier, 113*2e192b24SSimon Glass * we need complete FIT image in RAM first */ 114*2e192b24SSimon Glass if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) { 115*2e192b24SSimon Glass if (!fit_check_format(fit_hdr)) { 116*2e192b24SSimon Glass bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ); 117*2e192b24SSimon Glass puts("** Bad FIT image format\n"); 118*2e192b24SSimon Glass return 1; 119*2e192b24SSimon Glass } 120*2e192b24SSimon Glass bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK); 121*2e192b24SSimon Glass fit_print_contents(fit_hdr); 122*2e192b24SSimon Glass } 123*2e192b24SSimon Glass #endif 124*2e192b24SSimon Glass 125*2e192b24SSimon Glass flush_cache(addr, (cnt+1)*info.blksz); 126*2e192b24SSimon Glass 127*2e192b24SSimon Glass /* Loading ok, update default load address */ 128*2e192b24SSimon Glass load_addr = addr; 129*2e192b24SSimon Glass 130*2e192b24SSimon Glass return bootm_maybe_autostart(cmdtp, argv[0]); 131*2e192b24SSimon Glass } 132*2e192b24SSimon Glass #endif 133