summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorChe-Liang Chiou <clchiou@chromium.org>2011-07-19 16:28:44 +0800
committerSimon Glass <sjg@chromium.org>2011-08-29 10:59:01 -0700
commitf771480b4ce71d9863f8b6f87abe571b3209f97d (patch)
tree38b411850a5a7775a8f492eb94c3577c63afcc7e /lib
parent0eaae2c7b2d0829bff40daa5452935b076916479 (diff)
CHROMIUM: fix recovery boot hangs
When the developer switch is turned off, the recovery boot hangs deep inside call stack due to memory corruption caused by freeing a pointer twice. The pointer in question is allocated by VbExDiskGetInfo() and freed by VbExDiskFreeInfo(). When VbExDiskGetInfo() finds no storage device or encounters an error, it frees the VbDiskInfo pointer, but it still returns the pointer value to its caller. And its caller frees the pointer again anyway. So, when an error occurs or no storage device is available, the correct implementation of VbExDiskGetInfo() should either not freeing and returning the pointer, or freeing the pointer and returning NULL, but not anything in between. In additional to fix the free-twice bug, this patch also corrects the return value of VbExDiskGetInfo() when there are too many storage device available. This should be a success with warnings instead of an error. BUG=chromium-os:17462 TEST=manually tested on Kaen * Boot to Chrome OS on internal and external storage device through normal, developer, and recovery boot path. * The recovery boot path is tested with both developer switch on and off. Change-Id: I26026a86523b4b0f6c471c2a30a7394607a9c86b Reviewed-on: http://gerrit.chromium.org/gerrit/4297 Tested-by: Che-Liang Chiou <clchiou@chromium.org> Reviewed-by: Tom Wai-Hong Tam <waihong@chromium.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/vbexport/boot_device.c60
1 files changed, 33 insertions, 27 deletions
diff --git a/lib/vbexport/boot_device.c b/lib/vbexport/boot_device.c
index bb159e87dc..9efebd9351 100644
--- a/lib/vbexport/boot_device.c
+++ b/lib/vbexport/boot_device.c
@@ -89,21 +89,24 @@ static void init_usb_storage(void)
usb_stor_scan(/*mode=*/1);
}
-VbError_t VbExDiskGetInfo(VbDiskInfo** infos_ptr, uint32_t* count,
+VbError_t VbExDiskGetInfo(VbDiskInfo** infos_ptr, uint32_t* count_ptr,
uint32_t disk_flags)
{
VbDiskInfo *infos;
+ uint32_t count, flags;
struct mmc *m;
block_dev_desc_t *d;
int i;
+ *infos_ptr = NULL;
+ *count_ptr = 0;
+
infos = (VbDiskInfo *)VbExMalloc(sizeof(VbDiskInfo) * MAX_DISK_INFO);
- *infos_ptr = infos;
- *count = 0;
+ count = 0;
/* Detect all SD/MMC devices. */
for (i = 0; (m = find_mmc_device(i)) != NULL; i++) {
- uint32_t flags = get_dev_flags(&m->block_dev);
+ flags = get_dev_flags(&m->block_dev);
/* Skip this entry if the flags are not matched. */
if (!(flags & disk_flags))
@@ -115,42 +118,45 @@ VbError_t VbExDiskGetInfo(VbDiskInfo** infos_ptr, uint32_t* count,
continue;
}
- if (add_disk_info(&m->block_dev, infos, count)) {
+ if (add_disk_info(&m->block_dev, infos, &count)) {
/*
* If too many storage devices registered,
* returns as many disk infos as we could
* handle.
*/
- return 1;
+ goto out;
}
}
/* To speed up, skip detecting USB if not require removable devices. */
- if (disk_flags & VB_DISK_FLAG_REMOVABLE) {
- /* Detect all USB storage devices. */
- init_usb_storage();
- for (i = 0; (d = usb_stor_get_dev(i)) != NULL; i++) {
- uint32_t flags = get_dev_flags(d);
-
- /* Skip this entry if the flags are not matched. */
- if (!(flags & disk_flags))
- continue;
-
- if (add_disk_info(d, infos, count)) {
- /*
- * If too many storage devices registered,
- * returns as many disk infos as we could
- * handle.
- */
- return 1;
- }
+ if (!(disk_flags & VB_DISK_FLAG_REMOVABLE))
+ goto out;
+
+ /* Detect all USB storage devices. */
+ init_usb_storage();
+ for (i = 0; (d = usb_stor_get_dev(i)) != NULL; i++) {
+ flags = get_dev_flags(d);
+
+ /* Skip this entry if the flags are not matched. */
+ if (!(flags & disk_flags))
+ continue;
+
+ if (add_disk_info(d, infos, &count)) {
+ /*
+ * If too many storage devices registered,
+ * returns as many disk infos as we could
+ * handle.
+ */
+ goto out;
}
}
- if (*count == 0) {
+out:
+ if (count) {
+ *infos_ptr = infos;
+ *count_ptr = count;
+ } else
VbExFree(infos);
- infos = NULL;
- }
return VBERROR_SUCCESS;
}