12e192b24SSimon Glass /* 22e192b24SSimon Glass * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 32e192b24SSimon Glass * Use of this source code is governed by a BSD-style license that can be 42e192b24SSimon Glass * found in the LICENSE file. 52e192b24SSimon Glass * 62e192b24SSimon Glass * Alternatively, this software may be distributed under the terms of the 72e192b24SSimon Glass * GNU General Public License ("GPL") version 2 as published by the Free 82e192b24SSimon Glass * Software Foundation. 92e192b24SSimon Glass */ 102e192b24SSimon Glass 112e192b24SSimon Glass #include <common.h> 122e192b24SSimon Glass #include <command.h> 132e192b24SSimon Glass #include <part.h> 142e192b24SSimon Glass 152e192b24SSimon Glass int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 162e192b24SSimon Glass { 172e192b24SSimon Glass char *ep; 184101f687SSimon Glass struct blk_desc *dev_desc = NULL; 192e192b24SSimon Glass int dev; 202e192b24SSimon Glass int part = 0; 212e192b24SSimon Glass disk_partition_t part_info; 222e192b24SSimon Glass ulong offset = 0u; 232e192b24SSimon Glass ulong limit = 0u; 242e192b24SSimon Glass void *addr; 252e192b24SSimon Glass uint blk; 262e192b24SSimon Glass uint cnt; 272e192b24SSimon Glass 282e192b24SSimon Glass if (argc != 6) { 292e192b24SSimon Glass cmd_usage(cmdtp); 302e192b24SSimon Glass return 1; 312e192b24SSimon Glass } 322e192b24SSimon Glass 332e192b24SSimon Glass dev = (int)simple_strtoul(argv[2], &ep, 16); 342e192b24SSimon Glass if (*ep) { 352e192b24SSimon Glass if (*ep != ':') { 362e192b24SSimon Glass printf("Invalid block device %s\n", argv[2]); 372e192b24SSimon Glass return 1; 382e192b24SSimon Glass } 392e192b24SSimon Glass part = (int)simple_strtoul(++ep, NULL, 16); 402e192b24SSimon Glass } 412e192b24SSimon Glass 42db1d9e78SSimon Glass dev_desc = blk_get_dev(argv[1], dev); 432e192b24SSimon Glass if (dev_desc == NULL) { 442e192b24SSimon Glass printf("Block device %s %d not supported\n", argv[1], dev); 452e192b24SSimon Glass return 1; 462e192b24SSimon Glass } 472e192b24SSimon Glass 482e192b24SSimon Glass addr = (void *)simple_strtoul(argv[3], NULL, 16); 492e192b24SSimon Glass blk = simple_strtoul(argv[4], NULL, 16); 502e192b24SSimon Glass cnt = simple_strtoul(argv[5], NULL, 16); 512e192b24SSimon Glass 522e192b24SSimon Glass if (part != 0) { 53*3e8bd469SSimon Glass if (part_get_info(dev_desc, part, &part_info)) { 542e192b24SSimon Glass printf("Cannot find partition %d\n", part); 552e192b24SSimon Glass return 1; 562e192b24SSimon Glass } 572e192b24SSimon Glass offset = part_info.start; 582e192b24SSimon Glass limit = part_info.size; 592e192b24SSimon Glass } else { 604101f687SSimon Glass /* Largest address not available in struct blk_desc. */ 612e192b24SSimon Glass limit = ~0; 622e192b24SSimon Glass } 632e192b24SSimon Glass 642e192b24SSimon Glass if (cnt + blk > limit) { 652e192b24SSimon Glass printf("Read out of range\n"); 662e192b24SSimon Glass return 1; 672e192b24SSimon Glass } 682e192b24SSimon Glass 692e192b24SSimon Glass if (dev_desc->block_read(dev_desc, offset + blk, cnt, addr) < 0) { 702e192b24SSimon Glass printf("Error reading blocks\n"); 712e192b24SSimon Glass return 1; 722e192b24SSimon Glass } 732e192b24SSimon Glass 742e192b24SSimon Glass return 0; 752e192b24SSimon Glass } 762e192b24SSimon Glass 772e192b24SSimon Glass U_BOOT_CMD( 782e192b24SSimon Glass read, 6, 0, do_read, 792e192b24SSimon Glass "Load binary data from a partition", 802e192b24SSimon Glass "<interface> <dev[:part]> addr blk# cnt" 812e192b24SSimon Glass ); 82