16eef6eacSSimon Glass /*
26eef6eacSSimon Glass * Copyright (C) 2016 Google, Inc
36eef6eacSSimon Glass * Written by Simon Glass <sjg@chromium.org>
46eef6eacSSimon Glass *
56eef6eacSSimon Glass * SPDX-License-Identifier: GPL-2.0+
66eef6eacSSimon Glass */
76eef6eacSSimon Glass
86eef6eacSSimon Glass #include <common.h>
96eef6eacSSimon Glass #include <linux/err.h>
106eef6eacSSimon Glass
blk_driver_lookup_type(int if_type)116eef6eacSSimon Glass struct blk_driver *blk_driver_lookup_type(int if_type)
126eef6eacSSimon Glass {
136eef6eacSSimon Glass struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver);
146eef6eacSSimon Glass const int n_ents = ll_entry_count(struct blk_driver, blk_driver);
156eef6eacSSimon Glass struct blk_driver *entry;
166eef6eacSSimon Glass
176eef6eacSSimon Glass for (entry = drv; entry != drv + n_ents; entry++) {
186eef6eacSSimon Glass if (if_type == entry->if_type)
196eef6eacSSimon Glass return entry;
206eef6eacSSimon Glass }
216eef6eacSSimon Glass
226eef6eacSSimon Glass /* Not found */
236eef6eacSSimon Glass return NULL;
246eef6eacSSimon Glass }
256eef6eacSSimon Glass
blk_driver_lookup_typename(const char * if_typename)266eef6eacSSimon Glass static struct blk_driver *blk_driver_lookup_typename(const char *if_typename)
276eef6eacSSimon Glass {
286eef6eacSSimon Glass struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver);
296eef6eacSSimon Glass const int n_ents = ll_entry_count(struct blk_driver, blk_driver);
306eef6eacSSimon Glass struct blk_driver *entry;
316eef6eacSSimon Glass
326eef6eacSSimon Glass for (entry = drv; entry != drv + n_ents; entry++) {
336eef6eacSSimon Glass if (!strcmp(if_typename, entry->if_typename))
346eef6eacSSimon Glass return entry;
356eef6eacSSimon Glass }
366eef6eacSSimon Glass
376eef6eacSSimon Glass /* Not found */
386eef6eacSSimon Glass return NULL;
396eef6eacSSimon Glass }
406eef6eacSSimon Glass
blk_get_if_type_name(enum if_type if_type)41*6faa4ed7SSimon Glass const char *blk_get_if_type_name(enum if_type if_type)
42*6faa4ed7SSimon Glass {
43*6faa4ed7SSimon Glass struct blk_driver *drv = blk_driver_lookup_type(if_type);
44*6faa4ed7SSimon Glass
45*6faa4ed7SSimon Glass return drv ? drv->if_typename : NULL;
46*6faa4ed7SSimon Glass }
47*6faa4ed7SSimon Glass
486eef6eacSSimon Glass /**
496eef6eacSSimon Glass * get_desc() - Get the block device descriptor for the given device number
506eef6eacSSimon Glass *
516eef6eacSSimon Glass * @drv: Legacy block driver
526eef6eacSSimon Glass * @devnum: Device number (0 = first)
536eef6eacSSimon Glass * @descp: Returns block device descriptor on success
546eef6eacSSimon Glass * @return 0 on success, -ENODEV if there is no such device, -ENOSYS if the
556eef6eacSSimon Glass * driver does not provide a way to find a device, or other -ve on other
566eef6eacSSimon Glass * error.
576eef6eacSSimon Glass */
get_desc(struct blk_driver * drv,int devnum,struct blk_desc ** descp)586eef6eacSSimon Glass static int get_desc(struct blk_driver *drv, int devnum, struct blk_desc **descp)
596eef6eacSSimon Glass {
606eef6eacSSimon Glass if (drv->desc) {
616eef6eacSSimon Glass if (devnum < 0 || devnum >= drv->max_devs)
626eef6eacSSimon Glass return -ENODEV;
636eef6eacSSimon Glass *descp = &drv->desc[devnum];
646eef6eacSSimon Glass return 0;
656eef6eacSSimon Glass }
666eef6eacSSimon Glass if (!drv->get_dev)
676eef6eacSSimon Glass return -ENOSYS;
686eef6eacSSimon Glass
696eef6eacSSimon Glass return drv->get_dev(devnum, descp);
706eef6eacSSimon Glass }
716eef6eacSSimon Glass
726eef6eacSSimon Glass #ifdef HAVE_BLOCK_DEVICE
blk_list_part(enum if_type if_type)736eef6eacSSimon Glass int blk_list_part(enum if_type if_type)
746eef6eacSSimon Glass {
756eef6eacSSimon Glass struct blk_driver *drv;
766eef6eacSSimon Glass struct blk_desc *desc;
776eef6eacSSimon Glass int devnum, ok;
786eef6eacSSimon Glass bool first = true;
796eef6eacSSimon Glass
806eef6eacSSimon Glass drv = blk_driver_lookup_type(if_type);
816eef6eacSSimon Glass if (!drv)
826eef6eacSSimon Glass return -ENOSYS;
836eef6eacSSimon Glass for (ok = 0, devnum = 0; devnum < drv->max_devs; ++devnum) {
846eef6eacSSimon Glass if (get_desc(drv, devnum, &desc))
856eef6eacSSimon Glass continue;
866eef6eacSSimon Glass if (desc->part_type != PART_TYPE_UNKNOWN) {
876eef6eacSSimon Glass ++ok;
886eef6eacSSimon Glass if (!first)
896eef6eacSSimon Glass putc('\n');
906eef6eacSSimon Glass part_print(desc);
916eef6eacSSimon Glass first = false;
926eef6eacSSimon Glass }
936eef6eacSSimon Glass }
946eef6eacSSimon Glass if (!ok)
956eef6eacSSimon Glass return -ENODEV;
966eef6eacSSimon Glass
976eef6eacSSimon Glass return 0;
986eef6eacSSimon Glass }
996eef6eacSSimon Glass
blk_print_part_devnum(enum if_type if_type,int devnum)1006eef6eacSSimon Glass int blk_print_part_devnum(enum if_type if_type, int devnum)
1016eef6eacSSimon Glass {
1026eef6eacSSimon Glass struct blk_driver *drv = blk_driver_lookup_type(if_type);
1036eef6eacSSimon Glass struct blk_desc *desc;
1046eef6eacSSimon Glass int ret;
1056eef6eacSSimon Glass
1066eef6eacSSimon Glass if (!drv)
1076eef6eacSSimon Glass return -ENOSYS;
1086eef6eacSSimon Glass ret = get_desc(drv, devnum, &desc);
1096eef6eacSSimon Glass if (ret)
1106eef6eacSSimon Glass return ret;
1116eef6eacSSimon Glass if (desc->type == DEV_TYPE_UNKNOWN)
1126eef6eacSSimon Glass return -ENOENT;
1136eef6eacSSimon Glass part_print(desc);
1146eef6eacSSimon Glass
1156eef6eacSSimon Glass return 0;
1166eef6eacSSimon Glass }
1176eef6eacSSimon Glass
blk_list_devices(enum if_type if_type)1186eef6eacSSimon Glass void blk_list_devices(enum if_type if_type)
1196eef6eacSSimon Glass {
1206eef6eacSSimon Glass struct blk_driver *drv = blk_driver_lookup_type(if_type);
1216eef6eacSSimon Glass struct blk_desc *desc;
1226eef6eacSSimon Glass int i;
1236eef6eacSSimon Glass
1246eef6eacSSimon Glass if (!drv)
1256eef6eacSSimon Glass return;
1266eef6eacSSimon Glass for (i = 0; i < drv->max_devs; ++i) {
1276eef6eacSSimon Glass if (get_desc(drv, i, &desc))
1286eef6eacSSimon Glass continue;
1296eef6eacSSimon Glass if (desc->type == DEV_TYPE_UNKNOWN)
1306eef6eacSSimon Glass continue; /* list only known devices */
1316eef6eacSSimon Glass printf("Device %d: ", i);
1326eef6eacSSimon Glass dev_print(desc);
1336eef6eacSSimon Glass }
1346eef6eacSSimon Glass }
1356eef6eacSSimon Glass
blk_print_device_num(enum if_type if_type,int devnum)1366eef6eacSSimon Glass int blk_print_device_num(enum if_type if_type, int devnum)
1376eef6eacSSimon Glass {
1386eef6eacSSimon Glass struct blk_driver *drv = blk_driver_lookup_type(if_type);
1396eef6eacSSimon Glass struct blk_desc *desc;
1406eef6eacSSimon Glass int ret;
1416eef6eacSSimon Glass
1426eef6eacSSimon Glass if (!drv)
1436eef6eacSSimon Glass return -ENOSYS;
1446eef6eacSSimon Glass ret = get_desc(drv, devnum, &desc);
1456eef6eacSSimon Glass if (ret)
1466eef6eacSSimon Glass return ret;
1476eef6eacSSimon Glass printf("\n%s device %d: ", drv->if_typename, devnum);
1486eef6eacSSimon Glass dev_print(desc);
1496eef6eacSSimon Glass
1506eef6eacSSimon Glass return 0;
1516eef6eacSSimon Glass }
1526eef6eacSSimon Glass
blk_show_device(enum if_type if_type,int devnum)1536eef6eacSSimon Glass int blk_show_device(enum if_type if_type, int devnum)
1546eef6eacSSimon Glass {
1556eef6eacSSimon Glass struct blk_driver *drv = blk_driver_lookup_type(if_type);
1566eef6eacSSimon Glass struct blk_desc *desc;
1576eef6eacSSimon Glass int ret;
1586eef6eacSSimon Glass
1596eef6eacSSimon Glass if (!drv)
1606eef6eacSSimon Glass return -ENOSYS;
1616eef6eacSSimon Glass printf("\nDevice %d: ", devnum);
1626eef6eacSSimon Glass if (devnum >= drv->max_devs) {
1636eef6eacSSimon Glass puts("unknown device\n");
1646eef6eacSSimon Glass return -ENODEV;
1656eef6eacSSimon Glass }
1666eef6eacSSimon Glass ret = get_desc(drv, devnum, &desc);
1676eef6eacSSimon Glass if (ret)
1686eef6eacSSimon Glass return ret;
1696eef6eacSSimon Glass dev_print(desc);
1706eef6eacSSimon Glass
1716eef6eacSSimon Glass if (desc->type == DEV_TYPE_UNKNOWN)
1726eef6eacSSimon Glass return -ENOENT;
1736eef6eacSSimon Glass
1746eef6eacSSimon Glass return 0;
1756eef6eacSSimon Glass }
1766eef6eacSSimon Glass #endif /* HAVE_BLOCK_DEVICE */
1776eef6eacSSimon Glass
blk_get_devnum_by_type(enum if_type if_type,int devnum)1786eef6eacSSimon Glass struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
1796eef6eacSSimon Glass {
1806eef6eacSSimon Glass struct blk_driver *drv = blk_driver_lookup_type(if_type);
1816eef6eacSSimon Glass struct blk_desc *desc;
1826eef6eacSSimon Glass
1836eef6eacSSimon Glass if (!drv)
1846eef6eacSSimon Glass return NULL;
1856eef6eacSSimon Glass
1866eef6eacSSimon Glass if (get_desc(drv, devnum, &desc))
1876eef6eacSSimon Glass return NULL;
1886eef6eacSSimon Glass
1896eef6eacSSimon Glass return desc;
1906eef6eacSSimon Glass }
1916eef6eacSSimon Glass
blk_dselect_hwpart(struct blk_desc * desc,int hwpart)1926eef6eacSSimon Glass int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
1936eef6eacSSimon Glass {
1946eef6eacSSimon Glass struct blk_driver *drv = blk_driver_lookup_type(desc->if_type);
1956eef6eacSSimon Glass
1966eef6eacSSimon Glass if (!drv)
1976eef6eacSSimon Glass return -ENOSYS;
1986eef6eacSSimon Glass if (drv->select_hwpart)
1996eef6eacSSimon Glass return drv->select_hwpart(desc, hwpart);
2006eef6eacSSimon Glass
2016eef6eacSSimon Glass return 0;
2026eef6eacSSimon Glass }
2036eef6eacSSimon Glass
blk_get_devnum_by_typename(const char * if_typename,int devnum)2046eef6eacSSimon Glass struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum)
2056eef6eacSSimon Glass {
2066eef6eacSSimon Glass struct blk_driver *drv = blk_driver_lookup_typename(if_typename);
2076eef6eacSSimon Glass struct blk_desc *desc;
2086eef6eacSSimon Glass
2096eef6eacSSimon Glass if (!drv)
2106eef6eacSSimon Glass return NULL;
2116eef6eacSSimon Glass
2126eef6eacSSimon Glass if (get_desc(drv, devnum, &desc))
2136eef6eacSSimon Glass return NULL;
2146eef6eacSSimon Glass
2156eef6eacSSimon Glass return desc;
2166eef6eacSSimon Glass }
2176eef6eacSSimon Glass
blk_read_devnum(enum if_type if_type,int devnum,lbaint_t start,lbaint_t blkcnt,void * buffer)2186eef6eacSSimon Glass ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start,
2196eef6eacSSimon Glass lbaint_t blkcnt, void *buffer)
2206eef6eacSSimon Glass {
2216eef6eacSSimon Glass struct blk_driver *drv = blk_driver_lookup_type(if_type);
2226eef6eacSSimon Glass struct blk_desc *desc;
2236eef6eacSSimon Glass ulong n;
2246eef6eacSSimon Glass int ret;
2256eef6eacSSimon Glass
2266eef6eacSSimon Glass if (!drv)
2276eef6eacSSimon Glass return -ENOSYS;
2286eef6eacSSimon Glass ret = get_desc(drv, devnum, &desc);
2296eef6eacSSimon Glass if (ret)
2306eef6eacSSimon Glass return ret;
2316eef6eacSSimon Glass n = desc->block_read(desc, start, blkcnt, buffer);
2326eef6eacSSimon Glass if (IS_ERR_VALUE(n))
2336eef6eacSSimon Glass return n;
2346eef6eacSSimon Glass
2356eef6eacSSimon Glass return n;
2366eef6eacSSimon Glass }
2376eef6eacSSimon Glass
blk_write_devnum(enum if_type if_type,int devnum,lbaint_t start,lbaint_t blkcnt,const void * buffer)2386eef6eacSSimon Glass ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
2396eef6eacSSimon Glass lbaint_t blkcnt, const void *buffer)
2406eef6eacSSimon Glass {
2416eef6eacSSimon Glass struct blk_driver *drv = blk_driver_lookup_type(if_type);
2426eef6eacSSimon Glass struct blk_desc *desc;
2436eef6eacSSimon Glass int ret;
2446eef6eacSSimon Glass
2456eef6eacSSimon Glass if (!drv)
2466eef6eacSSimon Glass return -ENOSYS;
2476eef6eacSSimon Glass ret = get_desc(drv, devnum, &desc);
2486eef6eacSSimon Glass if (ret)
2496eef6eacSSimon Glass return ret;
2506eef6eacSSimon Glass return desc->block_write(desc, start, blkcnt, buffer);
2516eef6eacSSimon Glass }
2526eef6eacSSimon Glass
blk_select_hwpart_devnum(enum if_type if_type,int devnum,int hwpart)2536eef6eacSSimon Glass int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart)
2546eef6eacSSimon Glass {
2556eef6eacSSimon Glass struct blk_driver *drv = blk_driver_lookup_type(if_type);
2566eef6eacSSimon Glass struct blk_desc *desc;
2576eef6eacSSimon Glass int ret;
2586eef6eacSSimon Glass
2596eef6eacSSimon Glass if (!drv)
2606eef6eacSSimon Glass return -ENOSYS;
2616eef6eacSSimon Glass ret = get_desc(drv, devnum, &desc);
2626eef6eacSSimon Glass if (ret)
2636eef6eacSSimon Glass return ret;
2646eef6eacSSimon Glass return drv->select_hwpart(desc, hwpart);
2656eef6eacSSimon Glass }
266