Merge "Replace bootp with dhcp."
diff --git a/src/drivers/storage/mmc.c b/src/drivers/storage/mmc.c
index b413097..aca9f96 100644
--- a/src/drivers/storage/mmc.c
+++ b/src/drivers/storage/mmc.c
@@ -933,6 +933,10 @@
 	}
 	mmc_set_clock(mmc, clock);
 	mmc->lba = mmc->capacity / mmc->read_bl_len;
+	if (mmc->block_dev) {
+		mmc->block_dev->block_count = mmc->lba;
+		mmc->block_dev->block_size = mmc->read_bl_len;
+	}
 	return 0;
 }
 
@@ -959,13 +963,6 @@
 	return 0;
 }
 
-int mmc_register(MmcDevice *mmc)
-{
-	if (!mmc->b_max)
-		mmc->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
-	return 0;
-}
-
 int mmc_start_init(MmcDevice *mmc)
 {
 	int err;
@@ -1044,10 +1041,46 @@
 }
 
 /////////////////////////////////////////////////////////////////////////////
-// BlockDevice callbacks
+// BlockDevice utilities and callbacks
 
-lba_t block_mmc_read(struct BlockDev *dev, lba_t start, lba_t count,
-		     void *buffer)
+void block_mmc_refresh(ListNode *block_node, MmcDevice *mmc)
+{
+	assert(mmc && mmc->block_dev);
+	debug("%s: %s\n",mmc->block_dev->name, __func__);
+	if (mmc->has_init) {
+		list_remove(&mmc->block_dev->list_node);
+		mmc->has_init = 0;
+	}
+	if (mmc_init(mmc) == 0) {
+		list_insert_after(&mmc->block_dev->list_node, block_node);
+		printf("%s: %s: Card present.\n", __func__,
+		       mmc->block_dev->name);
+	} else {
+		printf("%s: %s: No card present.\n", __func__,
+		       mmc->block_dev->name);
+	}
+}
+
+int block_mmc_register(BlockDev *dev, MmcDevice *mmc, MmcDevice **root)
+{
+	if (!mmc->b_max)
+		mmc->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+	mmc->block_dev = dev;
+	dev->dev_data = mmc;
+	dev->read = block_mmc_read;
+	dev->write = block_mmc_write;
+	if (root) {
+		while (*root && (*root)->next)
+			root = &(*root)->next;
+		if (*root)
+			(*root)->next = mmc;
+		else
+			*root = mmc;
+	}
+	return 0;
+}
+
+lba_t block_mmc_read(BlockDev *dev, lba_t start, lba_t count, void *buffer)
 {
 	MmcDevice *mmc = (MmcDevice *)dev->dev_data;
 	lba_t cur, blocks_todo = count;
@@ -1071,7 +1104,7 @@
 	return count;
 }
 
-lba_t block_mmc_write(struct BlockDev *dev, lba_t start, lba_t count,
+lba_t block_mmc_write(BlockDev *dev, lba_t start, lba_t count,
 		      const void *buffer)
 {
 	MmcDevice *mmc = (MmcDevice *)dev->dev_data;
diff --git a/src/drivers/storage/mmc.h b/src/drivers/storage/mmc.h
index 3bc239f..70d7133 100644
--- a/src/drivers/storage/mmc.h
+++ b/src/drivers/storage/mmc.h
@@ -260,6 +260,8 @@
 	char op_cond_pending;  /* 1 if we are waiting on an op_cond command */
 	char init_in_progress;  /* 1 if we have done mmc_start_init() */
 	uint32_t op_cond_response;  /* the response byte from the last op_cond */
+	BlockDev *block_dev;
+	struct MmcDevice *next;  /* MMC device in same type (for refresh) */
 } MmcDevice;
 
 int mmc_busy_wait_io(volatile uint32_t *address, uint32_t *output,
@@ -267,7 +269,6 @@
 int mmc_busy_wait_io_until(volatile uint32_t *address, uint32_t *output,
 			   uint32_t io_mask, uint32_t timeout_ms);
 
-int mmc_register(MmcDevice *mmc);
 int mmc_init(MmcDevice *mmc);
 int mmc_start_init(MmcDevice *mmc);
 int mmc_is_card_present(MmcDevice *mmc);
@@ -277,9 +278,10 @@
 uint32_t mmc_write(MmcDevice *mmc, uint32_t start, lba_t block_count,
 		   const void *src);
 
-lba_t block_mmc_read(struct BlockDev *dev, lba_t start, lba_t count,
-		     void *buffer);
-lba_t block_mmc_write(struct BlockDev *dev, lba_t start, lba_t count,
+void block_mmc_refresh(ListNode *block_node, MmcDevice *mmc);
+int block_mmc_register(BlockDev *dev, MmcDevice *mmc, MmcDevice **root);
+lba_t block_mmc_read(BlockDev *dev, lba_t start, lba_t count, void *buffer);
+lba_t block_mmc_write(BlockDev *dev, lba_t start, lba_t count,
 		      const void *buffer);
 
 // Helper macros for alignment.
diff --git a/src/drivers/storage/s5p_mshc.c b/src/drivers/storage/s5p_mshc.c
index 3809755..97ded58 100644
--- a/src/drivers/storage/s5p_mshc.c
+++ b/src/drivers/storage/s5p_mshc.c
@@ -55,9 +55,11 @@
 {
 	switch(dev_index) {
 		case 0:
-			return (S5pMshci *)CONFIG_DRIVER_STORAGE_MSHC_S5P_MMC0_ADDRESS;
+			return ((S5pMshci *)
+				CONFIG_DRIVER_STORAGE_MSHC_S5P_MMC0_ADDRESS);
 		case 1:
-			return (S5pMshci *)CONFIG_DRIVER_STORAGE_MSHC_S5P_MMC1_ADDRESS;
+			return ((S5pMshci *)
+				CONFIG_DRIVER_STORAGE_MSHC_S5P_MMC1_ADDRESS);
 	}
 	error("Unknown device index (%d): Check your Kconfig settings for "
 	      "DRIVER_MSHC_S5P_DEVICES.\n", dev_index);
@@ -65,6 +67,11 @@
 	return NULL;
 }
 
+static int s5p_mshci_is_card_present(S5pMshci *reg)
+{
+	return !readl(&reg->cdetect);
+}
+
 static int mshci_setbits(MshciHost *host, unsigned int bits)
 {
 	setbits32(&host->reg->ctrl, bits);
@@ -462,19 +469,16 @@
 	writel(fifo_val, &host->reg->fifoth);
 }
 
-static int s5p_mshci_is_card_present(MmcDevice *mmc)
+static int mshci_is_card_present(MmcDevice *mmc)
 {
-        int present = 1; /* for ch0 (eMMC) card is always present */
+	BlockDev *block_dev = (BlockDev *)mmc->block_dev;
 	MshciHost *host = (MshciHost *)mmc->host;
+	assert(block_dev);
+
 	debug("%s\n", __func__);
-	switch(host->dev_index) {
-		case 0:  // MMC0 (eMMC) card is always present
-			return present;
-		case 1:  // Also known as PERIPH_ID_SDMMC2
-			return !readl(&host->reg->cdetect);
-	}
-	assert(host->dev_index == 0 || host->dev_index == 1);
-	return 0;
+	if (!block_dev->removable)
+		return 1;
+	return s5p_mshci_is_card_present(host->reg);
 }
 
 static int mshci_init(MshciHost *host)
@@ -533,9 +537,9 @@
 	return 0;
 }
 
-static int s5p_mshc_initialize(int dev_index, S5pMshci *reg)
+static int s5p_mshc_initialize(int dev_index, S5pMshci *reg,
+			       MmcDevice **refresh_list)
 {
-	ListNode *root = NULL;
 	int bus_width = 1;
 	const int name_size = 16;
 	char *name;
@@ -558,7 +562,7 @@
 	mmc_dev->send_cmd = s5p_mshci_send_command;
 	mmc_dev->set_ios = s5p_mshci_set_ios;
 	mmc_dev->init = s5p_mshci_init;
-	mmc_dev->is_card_present = s5p_mshci_is_card_present;
+	mmc_dev->is_card_present = mshci_is_card_present;
 
 	mmc_dev->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 	mmc_dev->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC;
@@ -566,43 +570,39 @@
 	mmc_dev->f_max = MAX_MSHCI_CLOCK;
 
 	name = malloc(name_size);
-	snprintf(name, name_size, "s5p_mshc %d", dev_index);
+	snprintf(name, name_size, "s5p_mshc%d", dev_index);
 	mshc_dev->name = name;
-	mshc_dev->dev_data = mmc_dev;
 	mshc_dev->block_size = reg->blksiz;
-	mshc_dev->read = block_mmc_read;
-	mshc_dev->write = block_mmc_write;
 
 	/* TODO(hungte) Get configuration data instead of hard-coded. */
 	if (dev_index == 0) {
 		bus_width = 8;
 		mshc_dev->removable = 0;
-		root = &fixed_block_devices;
 		mmc_dev->host_caps |= MMC_MODE_8BIT;
 	} else {
 		bus_width = 4;
 		mshc_dev->removable = 1;
-		root = &removable_block_devices;
 		mmc_dev->host_caps |= MMC_MODE_4BIT;
 	}
 	mmc_dev->bus_width = bus_width;
-	list_insert_after(&mshc_dev->list_node, root);
 
-	mmc_register(mmc_dev);
-	if (mmc_init(mmc_dev))
-		error("Failed to reset MMC card #%d.\n", dev_index);
-	else
-		debug("MMC%d: init success (reset OK).\n", dev_index);
+	if (mshc_dev->removable) {
+		block_mmc_register(mshc_dev, mmc_dev, refresh_list);
+		debug("%s: removable registered (init on refresh).\n", name);
+	} else {
+		block_mmc_register(mshc_dev, mmc_dev, NULL);
+		if (mmc_init(mmc_dev)) {
+			error("%s: failed to init fixed %s.\n", __func__, name);
+			free(name);
+			free(mmc_dev);
+			free(mshc_dev);
+			free(host);
+			return -1;
+		}
+		list_insert_after(&mshc_dev->list_node, &fixed_block_devices);
+		debug("%s:  init success (reset OK): %s\n", __func__, name);
+	}
 
-	// Update media size when mmc setup is ready.
-	mshc_dev->block_count = mmc_dev->lba;
-	mshc_dev->block_size = mmc_dev->read_bl_len;
-
-	debug("dev_index=%d, width=%d, reg=%p, removable=%d, "
-	      "block_size=%d, block_count=%d\n",
-	      dev_index, bus_width, reg, mshc_dev->removable,
-	      (int)mshc_dev->block_size,
-	      (int)mshc_dev->block_count);
 	return 0;
 }
 
@@ -612,10 +612,22 @@
 static void s5p_mshc_ctrlr_init(BlockDevCtrlr *ctrlr)
 {
 	int i;
+	MmcDevice **refresh_list = (MmcDevice **)(&ctrlr->ctrlr_data);
 
 	debug("%s started.\n", __func__);
-	for (i = 0; i < CONFIG_DRIVER_STORAGE_MSHC_S5P_DEVICES; i++)
-		s5p_mshc_initialize(i, s5p_get_base_mshci(i));
+	for (i = 0; i < CONFIG_DRIVER_STORAGE_MSHC_S5P_DEVICES; i++) {
+		s5p_mshc_initialize(i, s5p_get_base_mshci(i), refresh_list);
+	}
+}
+
+static void s5p_mshc_ctrlr_refresh(BlockDevCtrlr *ctrlr)
+{
+	MmcDevice *mmc = (MmcDevice *)ctrlr->ctrlr_data;
+	debug("%s: enter (root=%p).\n", __func__, mmc);
+	for (; mmc; mmc = mmc->next) {
+		block_mmc_refresh(&removable_block_devices, mmc);
+	}
+	debug("%s: leave.\n", __func__);
 }
 
 int s5p_mshc_ctrlr_register(void)
@@ -623,7 +635,8 @@
 	static BlockDevCtrlr s5p_mshc =
 	{
 		&s5p_mshc_ctrlr_init,
-		// TODO(hungte) Add refresh function.
+		&s5p_mshc_ctrlr_refresh,
+		NULL,
 	};
 	list_insert_after(&s5p_mshc.list_node, &block_dev_controllers);
 	debug("%s: done.\n", __func__);
diff --git a/src/vboot/Makefile.inc b/src/vboot/Makefile.inc
index 1623430..fd42b51 100644
--- a/src/vboot/Makefile.inc
+++ b/src/vboot/Makefile.inc
@@ -63,6 +63,7 @@
 else
 	@printf "    MAKE       $(subst $(obj)/,,$(@))\n"
 	$(Q)FIRMWARE_ARCH=$(VB_FIRMWARE_ARCH) \
+		CC="$(XCC)" \
 		CFLAGS="$(CFLAGS) -DVBOOT_DEBUG" \
 		make -C $(VB_SOURCE) \
 		MOCK_TPM=$(VBOOT_MOCK_TPM) \