Merge branch 'master' of git://git.denx.de/u-boot-socfpga
[platform/kernel/u-boot.git] / cmd / read.c
1 /*
2  * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  *
6  * Alternatively, this software may be distributed under the terms of the
7  * GNU General Public License ("GPL") version 2 as published by the Free
8  * Software Foundation.
9  */
10
11 #include <common.h>
12 #include <command.h>
13 #include <part.h>
14
15 int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
16 {
17         char *ep;
18         block_dev_desc_t *dev_desc = NULL;
19         int dev;
20         int part = 0;
21         disk_partition_t part_info;
22         ulong offset = 0u;
23         ulong limit = 0u;
24         void *addr;
25         uint blk;
26         uint cnt;
27
28         if (argc != 6) {
29                 cmd_usage(cmdtp);
30                 return 1;
31         }
32
33         dev = (int)simple_strtoul(argv[2], &ep, 16);
34         if (*ep) {
35                 if (*ep != ':') {
36                         printf("Invalid block device %s\n", argv[2]);
37                         return 1;
38                 }
39                 part = (int)simple_strtoul(++ep, NULL, 16);
40         }
41
42         dev_desc = get_dev(argv[1], dev);
43         if (dev_desc == NULL) {
44                 printf("Block device %s %d not supported\n", argv[1], dev);
45                 return 1;
46         }
47
48         addr = (void *)simple_strtoul(argv[3], NULL, 16);
49         blk = simple_strtoul(argv[4], NULL, 16);
50         cnt = simple_strtoul(argv[5], NULL, 16);
51
52         if (part != 0) {
53                 if (get_partition_info(dev_desc, part, &part_info)) {
54                         printf("Cannot find partition %d\n", part);
55                         return 1;
56                 }
57                 offset = part_info.start;
58                 limit = part_info.size;
59         } else {
60                 /* Largest address not available in block_dev_desc_t. */
61                 limit = ~0;
62         }
63
64         if (cnt + blk > limit) {
65                 printf("Read out of range\n");
66                 return 1;
67         }
68
69         if (dev_desc->block_read(dev_desc, offset + blk, cnt, addr) < 0) {
70                 printf("Error reading blocks\n");
71                 return 1;
72         }
73
74         return 0;
75 }
76
77 U_BOOT_CMD(
78         read,   6,      0,      do_read,
79         "Load binary data from a partition",
80         "<interface> <dev[:part]> addr blk# cnt"
81 );