Merge git://git.denx.de/u-boot-x86
diff --git a/README b/README
index 4ca04d0..42ece99 100644
--- a/README
+++ b/README
@@ -1773,6 +1773,15 @@
 		regarding the non-volatile storage device. Define this to
 		the eMMC device that fastboot should use to store the image.
 
+		CONFIG_FASTBOOT_GPT_NAME
+		The fastboot "flash" command supports writing the downloaded
+		image to the Protective MBR and the Primary GUID Partition
+		Table. (Additionally, this downloaded image is post-processed
+		to generate and write the Backup GUID Partition Table.)
+		This occurs when the specified "partition name" on the
+		"fastboot flash" command line matches this value.
+		Default is GPT_ENTRY_NAME (currently "gpt") if undefined.
+
 - Journaling Flash filesystem support:
 		CONFIG_JFFS2_NAND, CONFIG_JFFS2_NAND_OFF, CONFIG_JFFS2_NAND_SIZE,
 		CONFIG_JFFS2_NAND_DEV
diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
index 9e020b4..e975abe 100644
--- a/common/cmd_dfu.c
+++ b/common/cmd_dfu.c
@@ -38,10 +38,10 @@
 
 	int controller_index = simple_strtoul(usb_controller, NULL, 0);
 	board_usb_init(controller_index, USB_INIT_DEVICE);
-	dfu_clear_detach();
+	g_dnl_clear_detach();
 	g_dnl_register("usb_dnl_dfu");
 	while (1) {
-		if (dfu_detach()) {
+		if (g_dnl_detach()) {
 			/*
 			 * Check if USB bus reset is performed after detach,
 			 * which indicates that -R switch has been passed to
@@ -74,7 +74,7 @@
 	if (dfu_reset)
 		run_command("reset", 0);
 
-	dfu_clear_detach();
+	g_dnl_clear_detach();
 
 	return ret;
 }
diff --git a/common/cmd_fastboot.c b/common/cmd_fastboot.c
index 909616d..b72f4f3 100644
--- a/common/cmd_fastboot.c
+++ b/common/cmd_fastboot.c
@@ -15,17 +15,21 @@
 {
 	int ret;
 
+	g_dnl_clear_detach();
 	ret = g_dnl_register("usb_dnl_fastboot");
 	if (ret)
 		return ret;
 
 	while (1) {
+		if (g_dnl_detach())
+			break;
 		if (ctrlc())
 			break;
 		usb_gadget_handle_interrupts();
 	}
 
 	g_dnl_unregister();
+	g_dnl_clear_detach();
 	return CMD_RET_SUCCESS;
 }
 
diff --git a/common/fb_mmc.c b/common/fb_mmc.c
index fb06d8a..6ea3938 100644
--- a/common/fb_mmc.c
+++ b/common/fb_mmc.c
@@ -4,12 +4,17 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#include <config.h>
 #include <common.h>
 #include <fb_mmc.h>
 #include <part.h>
 #include <aboot.h>
 #include <sparse_format.h>
 
+#ifndef CONFIG_FASTBOOT_GPT_NAME
+#define CONFIG_FASTBOOT_GPT_NAME GPT_ENTRY_NAME
+#endif
+
 /* The 64 defined bytes plus the '\0' */
 #define RESPONSE_LEN	(64 + 1)
 
@@ -62,7 +67,6 @@
 void fb_mmc_flash_write(const char *cmd, void *download_buffer,
 			unsigned int download_bytes, char *response)
 {
-	int ret;
 	block_dev_desc_t *dev_desc;
 	disk_partition_t info;
 
@@ -76,8 +80,24 @@
 		return;
 	}
 
-	ret = get_partition_info_efi_by_name(dev_desc, cmd, &info);
-	if (ret) {
+	if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0) {
+		printf("%s: updating MBR, Primary and Backup GPT(s)\n",
+		       __func__);
+		if (is_valid_gpt_buf(dev_desc, download_buffer)) {
+			printf("%s: invalid GPT - refusing to write to flash\n",
+			       __func__);
+			fastboot_fail("invalid GPT partition");
+			return;
+		}
+		if (write_mbr_and_gpt_partitions(dev_desc, download_buffer)) {
+			printf("%s: writing GPT partitions failed\n", __func__);
+			fastboot_fail("writing GPT partitions failed");
+			return;
+		}
+		printf("........ success\n");
+		fastboot_okay("");
+		return;
+	} else if (get_partition_info_efi_by_name(dev_desc, cmd, &info)) {
 		error("cannot find partition: '%s'\n", cmd);
 		fastboot_fail("cannot find partition");
 		return;
diff --git a/disk/part_efi.c b/disk/part_efi.c
index efed58f..338010e 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -69,6 +69,107 @@
 			sizeof(efi_guid_t));
 }
 
+static int validate_gpt_header(gpt_header *gpt_h, lbaint_t lba,
+		lbaint_t lastlba)
+{
+	uint32_t crc32_backup = 0;
+	uint32_t calc_crc32;
+
+	/* Check the GPT header signature */
+	if (le64_to_cpu(gpt_h->signature) != GPT_HEADER_SIGNATURE) {
+		printf("%s signature is wrong: 0x%llX != 0x%llX\n",
+		       "GUID Partition Table Header",
+		       le64_to_cpu(gpt_h->signature),
+		       GPT_HEADER_SIGNATURE);
+		return -1;
+	}
+
+	/* Check the GUID Partition Table CRC */
+	memcpy(&crc32_backup, &gpt_h->header_crc32, sizeof(crc32_backup));
+	memset(&gpt_h->header_crc32, 0, sizeof(gpt_h->header_crc32));
+
+	calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
+		le32_to_cpu(gpt_h->header_size));
+
+	memcpy(&gpt_h->header_crc32, &crc32_backup, sizeof(crc32_backup));
+
+	if (calc_crc32 != le32_to_cpu(crc32_backup)) {
+		printf("%s CRC is wrong: 0x%x != 0x%x\n",
+		       "GUID Partition Table Header",
+		       le32_to_cpu(crc32_backup), calc_crc32);
+		return -1;
+	}
+
+	/*
+	 * Check that the my_lba entry points to the LBA that contains the GPT
+	 */
+	if (le64_to_cpu(gpt_h->my_lba) != lba) {
+		printf("GPT: my_lba incorrect: %llX != " LBAF "\n",
+		       le64_to_cpu(gpt_h->my_lba),
+		       lba);
+		return -1;
+	}
+
+	/*
+	 * Check that the first_usable_lba and that the last_usable_lba are
+	 * within the disk.
+	 */
+	if (le64_to_cpu(gpt_h->first_usable_lba) > lastlba) {
+		printf("GPT: first_usable_lba incorrect: %llX > " LBAF "\n",
+		       le64_to_cpu(gpt_h->first_usable_lba), lastlba);
+		return -1;
+	}
+	if (le64_to_cpu(gpt_h->last_usable_lba) > lastlba) {
+		printf("GPT: last_usable_lba incorrect: %llX > " LBAF "\n",
+		       le64_to_cpu(gpt_h->last_usable_lba), lastlba);
+		return -1;
+	}
+
+	debug("GPT: first_usable_lba: %llX last_usable_lba: %llX last lba: "
+	      LBAF "\n", le64_to_cpu(gpt_h->first_usable_lba),
+	      le64_to_cpu(gpt_h->last_usable_lba), lastlba);
+
+	return 0;
+}
+
+static int validate_gpt_entries(gpt_header *gpt_h, gpt_entry *gpt_e)
+{
+	uint32_t calc_crc32;
+
+	/* Check the GUID Partition Table Entry Array CRC */
+	calc_crc32 = efi_crc32((const unsigned char *)gpt_e,
+		le32_to_cpu(gpt_h->num_partition_entries) *
+		le32_to_cpu(gpt_h->sizeof_partition_entry));
+
+	if (calc_crc32 != le32_to_cpu(gpt_h->partition_entry_array_crc32)) {
+		printf("%s: 0x%x != 0x%x\n",
+		       "GUID Partition Table Entry Array CRC is wrong",
+		       le32_to_cpu(gpt_h->partition_entry_array_crc32),
+		       calc_crc32);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void prepare_backup_gpt_header(gpt_header *gpt_h)
+{
+	uint32_t calc_crc32;
+	uint64_t val;
+
+	/* recalculate the values for the Backup GPT Header */
+	val = le64_to_cpu(gpt_h->my_lba);
+	gpt_h->my_lba = gpt_h->alternate_lba;
+	gpt_h->alternate_lba = cpu_to_le64(val);
+	gpt_h->partition_entry_lba =
+			cpu_to_le64(le64_to_cpu(gpt_h->last_usable_lba) + 1);
+	gpt_h->header_crc32 = 0;
+
+	calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
+			       le32_to_cpu(gpt_h->header_size));
+	gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
+}
+
 #ifdef CONFIG_EFI_PARTITION
 /*
  * Public Functions (include/part.h)
@@ -259,7 +360,6 @@
 	const int pte_blk_cnt = BLOCK_CNT((gpt_h->num_partition_entries
 					   * sizeof(gpt_entry)), dev_desc);
 	u32 calc_crc32;
-	u64 val;
 
 	debug("max lba: %x\n", (u32) dev_desc->lba);
 	/* Setup the Protective MBR */
@@ -284,15 +384,7 @@
 	    != pte_blk_cnt)
 		goto err;
 
-	/* recalculate the values for the Backup GPT Header */
-	val = le64_to_cpu(gpt_h->my_lba);
-	gpt_h->my_lba = gpt_h->alternate_lba;
-	gpt_h->alternate_lba = cpu_to_le64(val);
-	gpt_h->header_crc32 = 0;
-
-	calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
-			      le32_to_cpu(gpt_h->header_size));
-	gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
+	prepare_backup_gpt_header(gpt_h);
 
 	if (dev_desc->block_write(dev_desc->dev,
 				  (lbaint_t)le64_to_cpu(gpt_h->last_usable_lba)
@@ -455,6 +547,97 @@
 	free(gpt_h);
 	return ret;
 }
+
+int is_valid_gpt_buf(block_dev_desc_t *dev_desc, void *buf)
+{
+	gpt_header *gpt_h;
+	gpt_entry *gpt_e;
+
+	/* determine start of GPT Header in the buffer */
+	gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
+		       dev_desc->blksz);
+	if (validate_gpt_header(gpt_h, GPT_PRIMARY_PARTITION_TABLE_LBA,
+				dev_desc->lba))
+		return -1;
+
+	/* determine start of GPT Entries in the buffer */
+	gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
+		       dev_desc->blksz);
+	if (validate_gpt_entries(gpt_h, gpt_e))
+		return -1;
+
+	return 0;
+}
+
+int write_mbr_and_gpt_partitions(block_dev_desc_t *dev_desc, void *buf)
+{
+	gpt_header *gpt_h;
+	gpt_entry *gpt_e;
+	int gpt_e_blk_cnt;
+	lbaint_t lba;
+	int cnt;
+
+	if (is_valid_gpt_buf(dev_desc, buf))
+		return -1;
+
+	/* determine start of GPT Header in the buffer */
+	gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
+		       dev_desc->blksz);
+
+	/* determine start of GPT Entries in the buffer */
+	gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
+		       dev_desc->blksz);
+	gpt_e_blk_cnt = BLOCK_CNT((le32_to_cpu(gpt_h->num_partition_entries) *
+				   le32_to_cpu(gpt_h->sizeof_partition_entry)),
+				  dev_desc);
+
+	/* write MBR */
+	lba = 0;	/* MBR is always at 0 */
+	cnt = 1;	/* MBR (1 block) */
+	if (dev_desc->block_write(dev_desc->dev, lba, cnt, buf) != cnt) {
+		printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
+		       __func__, "MBR", cnt, lba);
+		return 1;
+	}
+
+	/* write Primary GPT */
+	lba = GPT_PRIMARY_PARTITION_TABLE_LBA;
+	cnt = 1;	/* GPT Header (1 block) */
+	if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_h) != cnt) {
+		printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
+		       __func__, "Primary GPT Header", cnt, lba);
+		return 1;
+	}
+
+	lba = le64_to_cpu(gpt_h->partition_entry_lba);
+	cnt = gpt_e_blk_cnt;
+	if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_e) != cnt) {
+		printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
+		       __func__, "Primary GPT Entries", cnt, lba);
+		return 1;
+	}
+
+	prepare_backup_gpt_header(gpt_h);
+
+	/* write Backup GPT */
+	lba = le64_to_cpu(gpt_h->partition_entry_lba);
+	cnt = gpt_e_blk_cnt;
+	if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_e) != cnt) {
+		printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
+		       __func__, "Backup GPT Entries", cnt, lba);
+		return 1;
+	}
+
+	lba = le64_to_cpu(gpt_h->my_lba);
+	cnt = 1;	/* GPT Header (1 block) */
+	if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_h) != cnt) {
+		printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
+		       __func__, "Backup GPT Header", cnt, lba);
+		return 1;
+	}
+
+	return 0;
+}
 #endif
 
 /*
@@ -511,10 +694,6 @@
 static int is_gpt_valid(block_dev_desc_t *dev_desc, u64 lba,
 			gpt_header *pgpt_head, gpt_entry **pgpt_pte)
 {
-	u32 crc32_backup = 0;
-	u32 calc_crc32;
-	u64 lastlba;
-
 	if (!dev_desc || !pgpt_head) {
 		printf("%s: Invalid Argument(s)\n", __func__);
 		return 0;
@@ -527,55 +706,8 @@
 		return 0;
 	}
 
-	/* Check the GPT header signature */
-	if (le64_to_cpu(pgpt_head->signature) != GPT_HEADER_SIGNATURE) {
-		printf("GUID Partition Table Header signature is wrong:"
-			"0x%llX != 0x%llX\n",
-			le64_to_cpu(pgpt_head->signature),
-			GPT_HEADER_SIGNATURE);
-		return 0;
-	}
-
-	/* Check the GUID Partition Table CRC */
-	memcpy(&crc32_backup, &pgpt_head->header_crc32, sizeof(crc32_backup));
-	memset(&pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32));
-
-	calc_crc32 = efi_crc32((const unsigned char *)pgpt_head,
-		le32_to_cpu(pgpt_head->header_size));
-
-	memcpy(&pgpt_head->header_crc32, &crc32_backup, sizeof(crc32_backup));
-
-	if (calc_crc32 != le32_to_cpu(crc32_backup)) {
-		printf("GUID Partition Table Header CRC is wrong:"
-			"0x%x != 0x%x\n",
-		       le32_to_cpu(crc32_backup), calc_crc32);
-		return 0;
-	}
-
-	/* Check that the my_lba entry points to the LBA that contains the GPT */
-	if (le64_to_cpu(pgpt_head->my_lba) != lba) {
-		printf("GPT: my_lba incorrect: %llX != %" PRIX64 "\n",
-		       le64_to_cpu(pgpt_head->my_lba),
-		       lba);
+	if (validate_gpt_header(pgpt_head, (lbaint_t)lba, dev_desc->lba))
 		return 0;
-	}
-
-	/* Check the first_usable_lba and last_usable_lba are within the disk. */
-	lastlba = (u64)dev_desc->lba;
-	if (le64_to_cpu(pgpt_head->first_usable_lba) > lastlba) {
-		printf("GPT: first_usable_lba incorrect: %llX > %" PRIX64 "\n",
-		       le64_to_cpu(pgpt_head->first_usable_lba), lastlba);
-		return 0;
-	}
-	if (le64_to_cpu(pgpt_head->last_usable_lba) > lastlba) {
-		printf("GPT: last_usable_lba incorrect: %llX > %" PRIX64 "\n",
-		       le64_to_cpu(pgpt_head->last_usable_lba), lastlba);
-		return 0;
-	}
-
-	debug("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %"
-	      PRIX64 "\n", le64_to_cpu(pgpt_head->first_usable_lba),
-	      le64_to_cpu(pgpt_head->last_usable_lba), lastlba);
 
 	/* Read and allocate Partition Table Entries */
 	*pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head);
@@ -584,17 +716,7 @@
 		return 0;
 	}
 
-	/* Check the GUID Partition Table Entry Array CRC */
-	calc_crc32 = efi_crc32((const unsigned char *)*pgpt_pte,
-		le32_to_cpu(pgpt_head->num_partition_entries) *
-		le32_to_cpu(pgpt_head->sizeof_partition_entry));
-
-	if (calc_crc32 != le32_to_cpu(pgpt_head->partition_entry_array_crc32)) {
-		printf("GUID Partition Table Entry Array CRC is wrong:"
-			"0x%x != 0x%x\n",
-			le32_to_cpu(pgpt_head->partition_entry_array_crc32),
-			calc_crc32);
-
+	if (validate_gpt_entries(pgpt_head, *pgpt_pte)) {
 		free(*pgpt_pte);
 		return 0;
 	}
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index 14cb366..ad0a7e7 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -17,7 +17,6 @@
 #include <linux/list.h>
 #include <linux/compiler.h>
 
-static bool dfu_detach_request;
 static LIST_HEAD(dfu_list);
 static int dfu_alt_num;
 static int alt_num_cnt;
@@ -39,21 +38,6 @@
 	return true;
 }
 
-bool dfu_detach(void)
-{
-	return dfu_detach_request;
-}
-
-void dfu_trigger_detach(void)
-{
-	dfu_detach_request = true;
-}
-
-void dfu_clear_detach(void)
-{
-	dfu_detach_request = false;
-}
-
 static int dfu_find_alt_num(const char *s)
 {
 	int i = 0;
@@ -111,8 +95,12 @@
 		return dfu_buf;
 
 	s = getenv("dfu_bufsiz");
-	dfu_buf_size = s ? (unsigned long)simple_strtol(s, NULL, 16) :
-			CONFIG_SYS_DFU_DATA_BUF_SIZE;
+	if (s)
+		dfu_buf_size = (unsigned long)simple_strtol(s, NULL, 0);
+
+	if (!s || !dfu_buf_size)
+		dfu_buf_size = CONFIG_SYS_DFU_DATA_BUF_SIZE;
+
 	if (dfu->max_buf_size && dfu_buf_size > dfu->max_buf_size)
 		dfu_buf_size = dfu->max_buf_size;
 
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index 72fa03e..62d72fe 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -40,10 +40,16 @@
 static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
 			u64 offset, void *buf, long *len)
 {
-	struct mmc *mmc = find_mmc_device(dfu->data.mmc.dev_num);
+	struct mmc *mmc;
 	u32 blk_start, blk_count, n = 0;
 	int ret, part_num_bkp = 0;
 
+	mmc = find_mmc_device(dfu->data.mmc.dev_num);
+	if (!mmc) {
+		error("Device MMC %d - not found!", dfu->data.mmc.dev_num);
+		return -ENODEV;
+	}
+
 	/*
 	 * We must ensure that we work in lba_blk_size chunks, so ALIGN
 	 * this value.
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 12628ef..fbc74f3 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -1062,7 +1062,6 @@
 	if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
 		DBG(DBG_BUS, "%s: RX data ready\n", ep->ep.name);
 		receive_data(ep);
-		usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
 	}
 }
 
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index 16fc9dd..ead71eb 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -366,7 +366,7 @@
 		to_runtime_mode(f_dfu);
 		f_dfu->dfu_state = DFU_STATE_appIDLE;
 
-		dfu_trigger_detach();
+		g_dnl_trigger_detach();
 		break;
 	default:
 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 71b62e5..310175a 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -480,6 +480,17 @@
 	fastboot_tx_write_str("OKAY");
 }
 
+static void do_exit_on_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	g_dnl_trigger_detach();
+}
+
+static void cb_continue(struct usb_ep *ep, struct usb_request *req)
+{
+	fastboot_func->in_req->complete = do_exit_on_complete;
+	fastboot_tx_write_str("OKAY");
+}
+
 #ifdef CONFIG_FASTBOOT_FLASH
 static void cb_flash(struct usb_ep *ep, struct usb_request *req)
 {
@@ -520,6 +531,9 @@
 	}, {
 		.cmd = "boot",
 		.cb = cb_boot,
+	}, {
+		.cmd = "continue",
+		.cb = cb_continue,
 	},
 #ifdef CONFIG_FASTBOOT_FLASH
 	{
diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
index 78519fa..2d0410d 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -205,12 +205,24 @@
 
 static int download_tail(long long int left, int cnt)
 {
-	struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num);
-	void *transfer_buffer = dfu_get_buf(dfu_entity);
+	struct dfu_entity *dfu_entity;
+	void *transfer_buffer;
 	int ret;
 
 	debug("%s: left: %llu cnt: %d\n", __func__, left, cnt);
 
+	dfu_entity = dfu_get_entity(alt_setting_num);
+	if (!dfu_entity) {
+		error("Alt setting: %d entity not found!\n", alt_setting_num);
+		return -ENOENT;
+	}
+
+	transfer_buffer = dfu_get_buf(dfu_entity);
+	if (!transfer_buffer) {
+		error("Transfer buffer not allocated!");
+		return -ENXIO;
+	}
+
 	if (left) {
 		ret = dfu_write(dfu_entity, transfer_buffer, left, cnt++);
 		if (ret) {
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index 25611ac..ee52a29 100644
--- a/drivers/usb/gadget/g_dnl.c
+++ b/drivers/usb/gadget/g_dnl.c
@@ -163,6 +163,23 @@
 	return -EOPNOTSUPP;
 }
 
+static bool g_dnl_detach_request;
+
+bool g_dnl_detach(void)
+{
+	return g_dnl_detach_request;
+}
+
+void g_dnl_trigger_detach(void)
+{
+	g_dnl_detach_request = true;
+}
+
+void g_dnl_clear_detach(void)
+{
+	g_dnl_detach_request = false;
+}
+
 static int g_dnl_get_bcd_device_number(struct usb_composite_dev *cdev)
 {
 	struct usb_gadget *gadget = cdev->gadget;
diff --git a/include/dfu.h b/include/dfu.h
index f1a71c7..c27856c 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -150,9 +150,6 @@
 char *dfu_extract_token(char** e, int *n);
 void dfu_trigger_reset(void);
 int dfu_get_alt(char *name);
-bool dfu_detach(void);
-void dfu_trigger_detach(void);
-void dfu_clear_detach(void);
 int dfu_init_env_entities(char *interface, char *devstr);
 unsigned char *dfu_get_buf(struct dfu_entity *dfu);
 unsigned char *dfu_free_buf(void);
diff --git a/include/g_dnl.h b/include/g_dnl.h
index 1b1b35e..4eeb5e4 100644
--- a/include/g_dnl.h
+++ b/include/g_dnl.h
@@ -39,4 +39,8 @@
 void g_dnl_unregister(void);
 void g_dnl_set_serialnumber(char *);
 
+bool g_dnl_detach(void);
+void g_dnl_trigger_detach(void);
+void g_dnl_clear_detach(void);
+
 #endif /* __G_DOWNLOAD_H_ */
diff --git a/include/part.h b/include/part.h
index a496a4a..8ea9b30 100644
--- a/include/part.h
+++ b/include/part.h
@@ -244,6 +244,26 @@
  */
 int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid,
 		disk_partition_t *partitions, const int parts_count);
+
+/**
+ * is_valid_gpt_buf() - Ensure that the Primary GPT information is valid
+ *
+ * @param dev_desc - block device descriptor
+ * @param buf - buffer which contains the MBR and Primary GPT info
+ *
+ * @return - '0' on success, otherwise error
+ */
+int is_valid_gpt_buf(block_dev_desc_t *dev_desc, void *buf);
+
+/**
+ * write_mbr_and_gpt_partitions() - write MBR, Primary GPT and Backup GPT
+ *
+ * @param dev_desc - block device descriptor
+ * @param buf - buffer which contains the MBR and Primary GPT info
+ *
+ * @return - '0' on success, otherwise error
+ */
+int write_mbr_and_gpt_partitions(block_dev_desc_t *dev_desc, void *buf);
 #endif
 
 #endif /* _PART_H */