]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/cmd_disk.c
combine block device load commands into common function
[karo-tx-uboot.git] / common / cmd_disk.c
1 /*
2  * (C) Copyright 2000-2011
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  *
23  */
24 #include <common.h>
25 #include <command.h>
26
27 int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc,
28                     char *const argv[])
29 {
30         char *boot_device = NULL;
31         char *ep;
32         int dev, part = 0;
33         ulong addr, cnt;
34         disk_partition_t info;
35         image_header_t *hdr;
36         block_dev_desc_t *dev_desc;
37
38 #if defined(CONFIG_FIT)
39         const void *fit_hdr = NULL;
40 #endif
41
42         bootstage_mark(BOOTSTAGE_ID_IDE_START);
43         switch (argc) {
44         case 1:
45                 addr = CONFIG_SYS_LOAD_ADDR;
46                 boot_device = getenv("bootdevice");
47                 break;
48         case 2:
49                 addr = simple_strtoul(argv[1], NULL, 16);
50                 boot_device = getenv("bootdevice");
51                 break;
52         case 3:
53                 addr = simple_strtoul(argv[1], NULL, 16);
54                 boot_device = argv[2];
55                 break;
56         default:
57                 bootstage_error(BOOTSTAGE_ID_IDE_ADDR);
58                 return CMD_RET_USAGE;
59         }
60         bootstage_mark(BOOTSTAGE_ID_IDE_ADDR);
61
62         if (!boot_device) {
63                 puts("\n** No boot device **\n");
64                 bootstage_error(BOOTSTAGE_ID_IDE_BOOT_DEVICE);
65                 return 1;
66         }
67         bootstage_mark(BOOTSTAGE_ID_IDE_BOOT_DEVICE);
68
69         dev = simple_strtoul(boot_device, &ep, 16);
70
71         dev_desc = get_dev(intf, dev);
72         if (dev_desc->type == DEV_TYPE_UNKNOWN) {
73                 printf("\n** Device %d not available\n", dev);
74                 bootstage_error(BOOTSTAGE_ID_IDE_TYPE);
75                 return 1;
76         }
77         bootstage_mark(BOOTSTAGE_ID_IDE_TYPE);
78
79         if (*ep) {
80                 if (*ep != ':') {
81                         puts("\n** Invalid boot device, use `dev[:part]' **\n");
82                         bootstage_error(BOOTSTAGE_ID_IDE_PART);
83                         return 1;
84                 }
85                 part = simple_strtoul(++ep, NULL, 16);
86         }
87         bootstage_mark(BOOTSTAGE_ID_IDE_PART);
88
89         if (get_partition_info(dev_desc, part, &info)) {
90                 bootstage_error(BOOTSTAGE_ID_IDE_PART_INFO);
91                 return 1;
92         }
93         bootstage_mark(BOOTSTAGE_ID_IDE_PART_INFO);
94
95         if ((strncmp((char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0)
96             &&
97             (strncmp((char *)info.type, BOOT_PART_COMP, sizeof(info.type)) != 0)
98            ) {
99                 printf("\n** Invalid partition type \"%.32s\"" " (expect \""
100                         BOOT_PART_TYPE "\")\n",
101                         info.type);
102                 bootstage_error(BOOTSTAGE_ID_IDE_PART_TYPE);
103                 return 1;
104         }
105         bootstage_mark(BOOTSTAGE_ID_IDE_PART_TYPE);
106
107         printf("\nLoading from disk device %d, partition %d: "
108                "Name: %.32s  Type: %.32s\n", dev, part, info.name, info.type);
109
110         debug("First Block: %ld,  # of blocks: %ld, Block Size: %ld\n",
111               info.start, info.size, info.blksz);
112
113         if (dev_desc->block_read(dev, info.start, 1, (ulong *) addr) != 1) {
114                 printf("** Read error on %d:%d\n", dev, part);
115                 bootstage_error(BOOTSTAGE_ID_IDE_PART_READ);
116                 return 1;
117         }
118         bootstage_mark(BOOTSTAGE_ID_IDE_PART_READ);
119
120         switch (genimg_get_format((void *) addr)) {
121         case IMAGE_FORMAT_LEGACY:
122                 hdr = (image_header_t *) addr;
123
124                 bootstage_mark(BOOTSTAGE_ID_IDE_FORMAT);
125
126                 if (!image_check_hcrc(hdr)) {
127                         puts("\n** Bad Header Checksum **\n");
128                         bootstage_error(BOOTSTAGE_ID_IDE_CHECKSUM);
129                         return 1;
130                 }
131                 bootstage_mark(BOOTSTAGE_ID_IDE_CHECKSUM);
132
133                 image_print_contents(hdr);
134
135                 cnt = image_get_image_size(hdr);
136                 break;
137 #if defined(CONFIG_FIT)
138         case IMAGE_FORMAT_FIT:
139                 fit_hdr = (const void *) addr;
140                 puts("Fit image detected...\n");
141
142                 cnt = fit_get_size(fit_hdr);
143                 break;
144 #endif
145         default:
146                 bootstage_error(BOOTSTAGE_ID_IDE_FORMAT);
147                 puts("** Unknown image type\n");
148                 return 1;
149         }
150
151         cnt += info.blksz - 1;
152         cnt /= info.blksz;
153         cnt -= 1;
154
155         if (dev_desc->block_read(dev, info.start + 1, cnt,
156                                          (ulong *)(addr + info.blksz)) != cnt) {
157                 printf("** Read error on %d:%d\n", dev, part);
158                 bootstage_error(BOOTSTAGE_ID_IDE_READ);
159                 return 1;
160         }
161         bootstage_mark(BOOTSTAGE_ID_IDE_READ);
162
163 #if defined(CONFIG_FIT)
164         /* This cannot be done earlier,
165          * we need complete FIT image in RAM first */
166         if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) {
167                 if (!fit_check_format(fit_hdr)) {
168                         bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ);
169                         puts("** Bad FIT image format\n");
170                         return 1;
171                 }
172                 bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK);
173                 fit_print_contents(fit_hdr);
174         }
175 #endif
176
177         flush_cache(addr, (cnt+1)*info.blksz);
178
179         /* Loading ok, update default load address */
180         load_addr = addr;
181
182         return bootm_maybe_autostart(cmdtp, argv[0]);
183 }