Add support for merged normal+dev firmware

BUG=chromium-os:17457
TEST=make && make runtests

When this is merged into an actual firmware build, can test it:
* dev switch off -> no dev screen, won't boot self-signed kernel
* dev switch on --> dev warning screen, will boot self-signed kernel
(e.g., it acts like the Cr-48)

Change-Id: I985428256e48b7e05dd4d8fe582a0c0103bf5fb2
Reviewed-on: http://gerrit.chromium.org/gerrit/3901
Reviewed-by: Stefan Reinauer <reinauer@google.com>
Tested-by: Randall Spangler <rspangler@chromium.org>
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index c5e97dd..11ff828 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -406,7 +406,6 @@
 }
 
 
-#ifdef BUILD_FVDEVELOPER
 /* Developer mode delays.  All must be multiples of DEV_DELAY_INCREMENT */
 #define DEV_DELAY_INCREMENT 250  /* Delay each loop, in msec */
 #define DEV_DELAY_BEEP1 20000    /* Beep for first time at this time */
@@ -479,8 +478,6 @@
   return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED);
 }
 
-#endif  /* BUILD_FVDEVELOPER */
-
 
 /* Delay between disk checks in recovery mode */
 #define REC_DELAY_INCREMENT 250
@@ -557,7 +554,7 @@
 VbError_t VbSelectAndLoadKernel(VbCommonParams* cparams,
                                 VbSelectAndLoadKernelParams* kparams) {
   VbSharedDataHeader* shared = (VbSharedDataHeader*)cparams->shared_data_blob;
-  VbError_t retval;
+  VbError_t retval = VBERROR_SUCCESS;
   LoadKernelParams p;
 
   VBDEBUG(("VbSelectAndLoadKernel() start\n"));
@@ -587,23 +584,39 @@
   if (shared->flags & VBSD_BOOT_DEV_SWITCH_ON)
     p.boot_flags |= BOOT_FLAG_DEVELOPER;
 
+  /* Handle separate normal and developer firmware builds. */
+#if defined(VBOOT_FIRMWARE_TYPE_NORMAL)
+  /* Normal-type firmware always acts like the dev switch is off. */
+  p.boot_flags &= ~BOOT_FLAG_DEVELOPER;
+#elif defined(VBOOT_FIRMWARE_TYPE_DEVELOPER)
+  /* Developer-type firmware fails if the dev switch is off. */
+  if (!(p.boot_flags & BOOT_FLAG_DEVELOPER)) {
+    /* Dev firmware should be signed with a key that only verifies
+     * when the dev switch is on, so we should never get here. */
+    VBDEBUG(("Developer firmware called with dev switch off!\n"));
+    VbSetRecoveryRequest(VBNV_RECOVERY_RW_DEV_MISMATCH);
+    retval = 1;
+  }
+#else
+  /* Recovery firmware, or merged normal+developer firmware.  No
+   * need to override flags. */
+#endif
+
   /* Select boot path */
-  if (shared->recovery_reason) {
+  if (VBERROR_SUCCESS != retval) {
+    /* Failure during setup; don't attempt booting a kernel */
+  } else if (shared->recovery_reason) {
     /* Recovery boot */
     p.boot_flags |= BOOT_FLAG_RECOVERY;
     retval = VbBootRecovery(cparams, &p);
     VbDisplayScreen(cparams, VB_SCREEN_BLANK, 0);
-  } else {
-    /* TODO: vboot compiler define for developer mode; this is the H2C one */
-#ifdef BUILD_FVDEVELOPER
+  } else if (p.boot_flags & BOOT_FLAG_DEVELOPER) {
     /* Developer boot */
-    p.boot_flags |= BOOT_FLAG_DEV_FIRMWARE;
     retval = VbBootDeveloper(cparams, &p);
     VbDisplayScreen(cparams, VB_SCREEN_BLANK, 0);
-#else
+  } else {
     /* Normal boot */
     retval = VbBootNormal(cparams, &p);
-#endif
   }
 
   if (VBERROR_SUCCESS == retval) {