[catalyst] Deliver zedboot via ipxe.

This change adds a single use endpoint to the NUC reboot server that
delivers the build's version of zedboot to the NUC. This will be used
in place of paving zedboot on NUCs eventually, but that change will
be in a following CL so that the current flow doesn't break.

Change-Id: I2e9098e6944c415080e3025d127941bb5c3d1f8e
diff --git a/cmd/catalyst/main.go b/cmd/catalyst/main.go
index bb3d16e..23ce096 100644
--- a/cmd/catalyst/main.go
+++ b/cmd/catalyst/main.go
@@ -28,6 +28,7 @@
 	// chainloaderExitStr instructs a NUC to exit IPXE and boot from disk
 	chainloaderExitStr = "#!ipxe\necho Catalyst chain loader\nexit 0\n"
 	rebootDuration     = 1 * time.Minute
+	zedbootPath        = "zedboot.zbi"
 )
 
 var (
@@ -98,12 +99,27 @@
 
 	mux := http.NewServeMux()
 	for _, device := range devices {
-		endpoint := fmt.Sprintf("/%s.ipxe", device.Mac())
-		mux.HandleFunc(endpoint, func(w http.ResponseWriter, r *http.Request) {
+		// Add endpoint for exit chainloader. This allows NUCs to reboot from disk.
+		mux.HandleFunc(fmt.Sprintf("/%s.ipxe", device.Mac()), func(w http.ResponseWriter, r *http.Request) {
 			w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s.ipxe", device.Mac()))
 			chainloader := strings.NewReader(chainloaderExitStr)
 			io.Copy(w, chainloader)
 		})
+
+		// Add single-use endpoint to deliver build's version of zedboot.
+		zedbootFile, err := os.Open(zedbootPath)
+		if err != nil {
+			zedbootFile = nil
+		}
+		mux.HandleFunc(fmt.Sprintf("/zedboot/%s", device.Mac()), func(w http.ResponseWriter, r *http.Request) {
+			if zedbootFile == nil {
+				return
+			}
+			w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", device.Mac()))
+			io.Copy(w, zedbootFile)
+			zedbootFile.Close()
+			zedbootFile = nil
+		})
 	}
 
 	srv := &http.Server{