mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-06-09 23:36:03 +09:00
api: storage: Add the missing write operation support
API_dev_write(va_list ap) is currently lacking the write support to storage devices because, historically, those devices did not implement block_write() The solution has been tested by loading and booting a (patched) GRUB instance in a QEMU vexpress-a9 environment. The disk write operations were triggered with GRUB's save_env command. Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@gmail.com>
This commit is contained in:
parent
0be2ecd486
commit
036218a671
59
api/api.c
59
api/api.c
|
@ -295,27 +295,31 @@ static int API_dev_close(va_list ap)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notice: this is for sending network packets only, as U-Boot does not
|
|
||||||
* support writing to storage at the moment (12.2007)
|
|
||||||
*
|
|
||||||
* pseudo signature:
|
* pseudo signature:
|
||||||
*
|
*
|
||||||
* int API_dev_write(
|
* int API_dev_write(
|
||||||
* struct device_info *di,
|
* struct device_info *di,
|
||||||
* void *buf,
|
* void *buf,
|
||||||
* int *len
|
* int *len,
|
||||||
|
* unsigned long *start
|
||||||
* )
|
* )
|
||||||
*
|
*
|
||||||
* buf: ptr to buffer from where to get the data to send
|
* buf: ptr to buffer from where to get the data to send
|
||||||
*
|
*
|
||||||
* len: length of packet to be sent (in bytes)
|
* len: ptr to length to be read
|
||||||
|
* - network: len of packet to be sent (in bytes)
|
||||||
|
* - storage: # of blocks to write (can vary in size depending on define)
|
||||||
*
|
*
|
||||||
|
* start: ptr to start block (only used for storage devices, ignored for
|
||||||
|
* network)
|
||||||
*/
|
*/
|
||||||
static int API_dev_write(va_list ap)
|
static int API_dev_write(va_list ap)
|
||||||
{
|
{
|
||||||
struct device_info *di;
|
struct device_info *di;
|
||||||
void *buf;
|
void *buf;
|
||||||
int *len;
|
lbasize_t *len_stor, act_len_stor;
|
||||||
|
lbastart_t *start;
|
||||||
|
int *len_net;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
/* 1. arg is ptr to the device_info struct */
|
/* 1. arg is ptr to the device_info struct */
|
||||||
|
@ -333,23 +337,36 @@ static int API_dev_write(va_list ap)
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return API_EINVAL;
|
return API_EINVAL;
|
||||||
|
|
||||||
/* 3. arg is length of buffer */
|
if (di->type & DEV_TYP_STOR) {
|
||||||
len = (int *)va_arg(ap, uintptr_t);
|
/* 3. arg - ptr to var with # of blocks to write */
|
||||||
if (len == NULL)
|
len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
|
||||||
return API_EINVAL;
|
if (!len_stor)
|
||||||
if (*len <= 0)
|
return API_EINVAL;
|
||||||
return API_EINVAL;
|
if (*len_stor <= 0)
|
||||||
|
return API_EINVAL;
|
||||||
|
|
||||||
if (di->type & DEV_TYP_STOR)
|
/* 4. arg - ptr to var with start block */
|
||||||
/*
|
start = (lbastart_t *)va_arg(ap, uintptr_t);
|
||||||
* write to storage is currently not supported by U-Boot:
|
|
||||||
* no storage device implements block_write() method
|
|
||||||
*/
|
|
||||||
return API_ENODEV;
|
|
||||||
|
|
||||||
else if (di->type & DEV_TYP_NET)
|
act_len_stor = dev_write_stor(di->cookie, buf, *len_stor, *start);
|
||||||
err = dev_write_net(di->cookie, buf, *len);
|
if (act_len_stor != *len_stor) {
|
||||||
else
|
debugf("write @ %llu: done %llu out of %llu blocks",
|
||||||
|
(uint64_t)blk, (uint64_t)act_len_stor,
|
||||||
|
(uint64_t)len_stor);
|
||||||
|
return API_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (di->type & DEV_TYP_NET) {
|
||||||
|
/* 3. arg points to the var with length of packet to write */
|
||||||
|
len_net = (int *)va_arg(ap, uintptr_t);
|
||||||
|
if (!len_net)
|
||||||
|
return API_EINVAL;
|
||||||
|
if (*len_net <= 0)
|
||||||
|
return API_EINVAL;
|
||||||
|
|
||||||
|
err = dev_write_net(di->cookie, buf, *len_net);
|
||||||
|
|
||||||
|
} else
|
||||||
err = API_ENODEV;
|
err = API_ENODEV;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -22,6 +22,7 @@ int dev_close_stor(void *);
|
||||||
int dev_close_net(void *);
|
int dev_close_net(void *);
|
||||||
|
|
||||||
lbasize_t dev_read_stor(void *, void *, lbasize_t, lbastart_t);
|
lbasize_t dev_read_stor(void *, void *, lbasize_t, lbastart_t);
|
||||||
|
lbasize_t dev_write_stor(void *, void *, lbasize_t, lbastart_t);
|
||||||
int dev_read_net(void *, void *, int);
|
int dev_read_net(void *, void *, int);
|
||||||
int dev_write_net(void *, void *, int);
|
int dev_write_net(void *, void *, int);
|
||||||
|
|
||||||
|
|
|
@ -349,3 +349,27 @@ lbasize_t dev_read_stor(void *cookie, void *buf, lbasize_t len, lbastart_t start
|
||||||
return dd->block_read(dd, start, len, buf);
|
return dd->block_read(dd, start, len, buf);
|
||||||
#endif /* defined(CONFIG_BLK) */
|
#endif /* defined(CONFIG_BLK) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lbasize_t dev_write_stor(void *cookie, void *buf, lbasize_t len, lbastart_t start)
|
||||||
|
{
|
||||||
|
struct blk_desc *dd = (struct blk_desc *)cookie;
|
||||||
|
int type = dev_stor_type(dd);
|
||||||
|
|
||||||
|
if (type == ENUM_MAX)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!dev_stor_is_valid(type, dd))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef CONFIG_BLK
|
||||||
|
return blk_dwrite(dd, start, len, buf);
|
||||||
|
#else
|
||||||
|
if (dd->block_write == NULL) {
|
||||||
|
debugf("no block_write() for device 0x%08x\n", cookie);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dd->block_write(dd, start, len, buf);
|
||||||
|
#endif /* defined(CONFIG_BLK) */
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user