Remove drive->desc field.

The description field is only available during the POST phase - it is
confusing to have it live in a structure available through all phases.

The description was only used by the boot menu code - pass each drive
description directly to the bootlist code.

Add a helper (znprintf) to automatically malloc_tmp the required
space.

Also, fixup ramdisk handling - it was using an incorrect floppy
priority.
diff --git a/src/ahci.c b/src/ahci.c
index 8fd2e14..b820e28 100644
--- a/src/ahci.c
+++ b/src/ahci.c
@@ -347,11 +347,6 @@
     port->drive.type = DTYPE_AHCI;
     port->drive.cntl_id = pnr;
     port->drive.removable = (buffer[0] & 0x80) ? 1 : 0;
-    port->drive.desc = malloc_tmp(MAXDESCSIZE);
-    if (!port->drive.desc) {
-        warn_noalloc();
-        return NULL;
-    }
 
     if (!port->atapi) {
         // found disk (ata)
@@ -372,32 +367,33 @@
             adjsize >>= 10;
             adjprefix = 'G';
         }
-        snprintf(port->drive.desc, MAXDESCSIZE
-                 , "AHCI/%d: %s ATA-%d Hard-Disk (%u %ciBytes)"
-                 , port->pnr
-                 , ata_extract_model(model, MAXMODEL, buffer)
-                 , ata_extract_version(buffer)
-                 , (u32)adjsize, adjprefix);
+        char *desc = znprintf(MAXDESCSIZE
+                              , "AHCI/%d: %s ATA-%d Hard-Disk (%u %ciBytes)"
+                              , port->pnr
+                              , ata_extract_model(model, MAXMODEL, buffer)
+                              , ata_extract_version(buffer)
+                              , (u32)adjsize, adjprefix);
+        dprintf(1, "%s\n", desc);
 
         // Register with bcv system.
-        boot_add_hd(&port->drive, -1);
+        boot_add_hd(&port->drive, desc, -1);
     } else {
         // found cdrom (atapi)
         port->drive.blksize = CDROM_SECTOR_SIZE;
         port->drive.sectors = (u64)-1;
         u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05;
-        snprintf(port->drive.desc, MAXDESCSIZE
-                 , "DVD/CD [AHCI/%d: %s ATAPI-%d %s]"
-                 , port->pnr
-                 , ata_extract_model(model, MAXMODEL, buffer)
-                 , ata_extract_version(buffer)
-                 , (iscd ? "DVD/CD" : "Device"));
+        char *desc = znprintf(MAXDESCSIZE
+                              , "DVD/CD [AHCI/%d: %s ATAPI-%d %s]"
+                              , port->pnr
+                              , ata_extract_model(model, MAXMODEL, buffer)
+                              , ata_extract_version(buffer)
+                              , (iscd ? "DVD/CD" : "Device"));
+        dprintf(1, "%s\n", desc);
 
         // fill cdidmap
         if (iscd)
-            boot_add_cd(&port->drive, -1);
+            boot_add_cd(&port->drive, desc, -1);
     }
-    dprintf(1, "%s\n", port->drive.desc);
 
     return port;
 
diff --git a/src/ata.c b/src/ata.c
index 86b89b5..e9a2aef 100644
--- a/src/ata.c
+++ b/src/ata.c
@@ -739,16 +739,12 @@
 static struct atadrive_s *
 init_atadrive(struct atadrive_s *dummy, u16 *buffer)
 {
-    char *desc = malloc_tmp(MAXDESCSIZE);
     struct atadrive_s *adrive_g = malloc_fseg(sizeof(*adrive_g));
-    if (!adrive_g || !desc) {
+    if (!adrive_g) {
         warn_noalloc();
-        free(desc);
-        free(adrive_g);
         return NULL;
     }
     memset(adrive_g, 0, sizeof(*adrive_g));
-    adrive_g->drive.desc = desc;
     adrive_g->chan_gf = dummy->chan_gf;
     adrive_g->slave = dummy->slave;
     adrive_g->drive.cntl_id = adrive_g->chan_gf->chanid * 2 + dummy->slave;
@@ -774,20 +770,20 @@
     adrive_g->drive.sectors = (u64)-1;
     u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05;
     char model[MAXMODEL+1];
-    snprintf(adrive_g->drive.desc, MAXDESCSIZE
-             , "DVD/CD [ata%d-%d: %s ATAPI-%d %s]"
-             , adrive_g->chan_gf->chanid, adrive_g->slave
-             , ata_extract_model(model, MAXMODEL, buffer)
-             , ata_extract_version(buffer)
-             , (iscd ? "DVD/CD" : "Device"));
-    dprintf(1, "%s\n", adrive_g->drive.desc);
+    char *desc = znprintf(MAXDESCSIZE
+                          , "DVD/CD [ata%d-%d: %s ATAPI-%d %s]"
+                          , adrive_g->chan_gf->chanid, adrive_g->slave
+                          , ata_extract_model(model, MAXMODEL, buffer)
+                          , ata_extract_version(buffer)
+                          , (iscd ? "DVD/CD" : "Device"));
+    dprintf(1, "%s\n", desc);
 
     // fill cdidmap
     if (iscd) {
         int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_bdf,
                                             adrive_g->chan_gf->chanid,
                                             adrive_g->slave);
-        boot_add_cd(&adrive_g->drive, prio);
+        boot_add_cd(&adrive_g->drive, desc, prio);
     }
 
     return adrive_g;
@@ -826,19 +822,19 @@
         adjprefix = 'G';
     }
     char model[MAXMODEL+1];
-    snprintf(adrive_g->drive.desc, MAXDESCSIZE
-             , "ata%d-%d: %s ATA-%d Hard-Disk (%u %ciBytes)"
-             , adrive_g->chan_gf->chanid, adrive_g->slave
-             , ata_extract_model(model, MAXMODEL, buffer)
-             , ata_extract_version(buffer)
-             , (u32)adjsize, adjprefix);
-    dprintf(1, "%s\n", adrive_g->drive.desc);
+    char *desc = znprintf(MAXDESCSIZE
+                          , "ata%d-%d: %s ATA-%d Hard-Disk (%u %ciBytes)"
+                          , adrive_g->chan_gf->chanid, adrive_g->slave
+                          , ata_extract_model(model, MAXMODEL, buffer)
+                          , ata_extract_version(buffer)
+                          , (u32)adjsize, adjprefix);
+    dprintf(1, "%s\n", desc);
 
     int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_bdf,
                                         adrive_g->chan_gf->chanid,
                                         adrive_g->slave);
     // Register with bcv system.
-    boot_add_hd(&adrive_g->drive, prio);
+    boot_add_hd(&adrive_g->drive, desc, prio);
 
     return adrive_g;
 }
diff --git a/src/boot.c b/src/boot.c
index 5bb179d..e83dcdc 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -166,7 +166,7 @@
     be->type = type;
     be->priority = prio;
     be->data = data;
-    be->description = desc;
+    be->description = desc ?: "?";
 
     // Add entry in sorted order.
     struct bootentry_s **pprev;
@@ -215,24 +215,24 @@
 }
 
 void
-boot_add_floppy(struct drive_s *drive_g, int prio)
+boot_add_floppy(struct drive_s *drive_g, const char *desc, int prio)
 {
     bootentry_add(IPL_TYPE_FLOPPY, defPrio(prio, DefaultFloppyPrio)
-                  , (u32)drive_g, drive_g->desc);
+                  , (u32)drive_g, desc);
 }
 
 void
-boot_add_hd(struct drive_s *drive_g, int prio)
+boot_add_hd(struct drive_s *drive_g, const char *desc, int prio)
 {
     bootentry_add(IPL_TYPE_HARDDISK, defPrio(prio, DefaultHDPrio)
-                  , (u32)drive_g, drive_g->desc);
+                  , (u32)drive_g, desc);
 }
 
 void
-boot_add_cd(struct drive_s *drive_g, int prio)
+boot_add_cd(struct drive_s *drive_g, const char *desc, int prio)
 {
     bootentry_add(IPL_TYPE_CDROM, defPrio(prio, DefaultCDPrio)
-                  , (u32)drive_g, drive_g->desc);
+                  , (u32)drive_g, desc);
 }
 
 // Add a CBFS payload entry
diff --git a/src/boot.h b/src/boot.h
index 107594b..8f56ccf 100644
--- a/src/boot.h
+++ b/src/boot.h
@@ -8,9 +8,9 @@
 void boot_add_bev(u16 seg, u16 bev, u16 desc, int prio);
 void boot_add_bcv(u16 seg, u16 ip, u16 desc, int prio);
 struct drive_s;
-void boot_add_floppy(struct drive_s *drive_g, int prio);
-void boot_add_hd(struct drive_s *drive_g, int prio);
-void boot_add_cd(struct drive_s *drive_g, int prio);
+void boot_add_floppy(struct drive_s *drive_g, const char *desc, int prio);
+void boot_add_hd(struct drive_s *drive_g, const char *desc, int prio);
+void boot_add_cd(struct drive_s *drive_g, const char *desc, int prio);
 void boot_add_cbfs(void *data, const char *desc, int prio);
 void boot_prep(void);
 int bootprio_find_pci_device(int bdf);
diff --git a/src/coreboot.c b/src/coreboot.c
index 503a6d2..b4dfd8a 100644
--- a/src/coreboot.c
+++ b/src/coreboot.c
@@ -604,10 +604,7 @@
         if (!file)
             break;
         const char *filename = cbfs_filename(file);
-        char *desc = malloc_tmp(MAXDESCSIZE);
-        if (!desc)
-            break;
-        snprintf(desc, MAXDESCSIZE, "Payload [%s]", &filename[4]);
+        char *desc = znprintf(MAXDESCSIZE, "Payload [%s]", &filename[4]);
         boot_add_cbfs(file, desc, -1);
     }
 }
diff --git a/src/disk.h b/src/disk.h
index b85a62d..f31de73 100644
--- a/src/disk.h
+++ b/src/disk.h
@@ -177,7 +177,6 @@
     u8 floppy_type;     // Type of floppy (only for floppy drives).
     struct chs_s lchs;  // Logical CHS
     u64 sectors;        // Total sectors count
-    char *desc;         // Drive description (only available during POST)
     u32 cntl_id;        // Unique id for a given driver type.
     u8 removable;       // Is media removable (currently unused)
 
@@ -232,7 +231,7 @@
 // floppy.c
 extern struct floppy_ext_dbt_s diskette_param_table2;
 void floppy_setup(void);
-struct drive_s *addFloppy(int floppyid, int ftype, int driver);
+struct drive_s *init_floppy(int floppyid, int ftype);
 int find_floppy_type(u32 size);
 int process_floppy_op(struct disk_op_s *op);
 void floppy_tick(void);
diff --git a/src/floppy.c b/src/floppy.c
index bfca63f..edc675d 100644
--- a/src/floppy.c
+++ b/src/floppy.c
@@ -92,38 +92,40 @@
 };
 
 struct drive_s *
-addFloppy(int floppyid, int ftype, int driver)
+init_floppy(int floppyid, int ftype)
 {
     if (ftype <= 0 || ftype >= ARRAY_SIZE(FloppyInfo)) {
         dprintf(1, "Bad floppy type %d\n", ftype);
         return NULL;
     }
 
-    char *desc = malloc_tmp(MAXDESCSIZE);
     struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g));
-    if (!drive_g || !desc) {
+    if (!drive_g) {
         warn_noalloc();
-        free(desc);
-        free(drive_g);
         return NULL;
     }
     memset(drive_g, 0, sizeof(*drive_g));
     drive_g->cntl_id = floppyid;
-    drive_g->type = driver;
+    drive_g->type = DTYPE_FLOPPY;
     drive_g->blksize = DISK_SECTOR_SIZE;
     drive_g->floppy_type = ftype;
     drive_g->sectors = (u64)-1;
-    drive_g->desc = desc;
-    snprintf(desc, MAXDESCSIZE, "Floppy [drive %c]", 'A' + floppyid);
 
     memcpy(&drive_g->lchs, &FloppyInfo[ftype].chs
            , sizeof(FloppyInfo[ftype].chs));
+    return drive_g;
+}
 
+static void
+addFloppy(int floppyid, int ftype)
+{
+    struct drive_s *drive_g = init_floppy(floppyid, ftype);
+    if (!drive_g)
+        return;
+    char *desc = znprintf(MAXDESCSIZE, "Floppy [drive %c]", 'A' + floppyid);
     int bdf = pci_find_class(PCI_CLASS_BRIDGE_ISA); /* isa-to-pci bridge */
     int prio = bootprio_find_fdc_device(bdf, PORT_FD_BASE, floppyid);
-
-    boot_add_floppy(drive_g, prio);
-    return drive_g;
+    boot_add_floppy(drive_g, desc, prio);
 }
 
 void
@@ -138,9 +140,9 @@
     } else {
         u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE);
         if (type & 0xf0)
-            addFloppy(0, type >> 4, DTYPE_FLOPPY);
+            addFloppy(0, type >> 4);
         if (type & 0x0f)
-            addFloppy(1, type & 0x0f, DTYPE_FLOPPY);
+            addFloppy(1, type & 0x0f);
     }
 
     outb(0x02, PORT_DMA1_MASK_REG);
diff --git a/src/output.c b/src/output.c
index 936d3d8..4c9f95b 100644
--- a/src/output.c
+++ b/src/output.c
@@ -148,6 +148,8 @@
 static void
 puts(struct putcinfo *action, const char *s)
 {
+    if (!MODESEGMENT && !s)
+        s = "(NULL)";
     for (; *s; s++)
         putc(action, *s);
 }
@@ -407,6 +409,30 @@
     return end - str;
 }
 
+// Build a formatted string - malloc'ing the memory.
+char *
+znprintf(size_t size, const char *fmt, ...)
+{
+    ASSERT32FLAT();
+    if (!size)
+        return NULL;
+    char *str = malloc_tmp(size);
+    if (!str) {
+        warn_noalloc();
+        return NULL;
+    }
+    struct snprintfinfo sinfo = { { putc_str }, str, str + size };
+    va_list args;
+    va_start(args, fmt);
+    bvprintf(&sinfo.info, fmt, args);
+    va_end(args);
+    char *end = sinfo.str;
+    if (end >= sinfo.end)
+        end = sinfo.end - 1;
+    *end = '\0';
+    return str;
+}
+
 
 /****************************************************************
  * Misc helpers
diff --git a/src/ramdisk.c b/src/ramdisk.c
index be1de56..5391376 100644
--- a/src/ramdisk.c
+++ b/src/ramdisk.c
@@ -9,6 +9,7 @@
 #include "memmap.h" // add_e820
 #include "biosvar.h" // GET_GLOBAL
 #include "bregs.h" // struct bregs
+#include "boot.h" // boot_add_floppy
 
 void
 ramdisk_setup(void)
@@ -40,10 +41,13 @@
     cbfs_copyfile(file, pos, size);
 
     // Setup driver.
-    dprintf(1, "Mapping CBFS floppy %s to addr %p\n", cbfs_filename(file), pos);
-    struct drive_s *drive_g = addFloppy((u32)pos, ftype, DTYPE_RAMDISK);
+    struct drive_s *drive_g = init_floppy((u32)pos, ftype);
     if (!drive_g)
-        strtcpy(drive_g->desc, cbfs_filename(file), MAXDESCSIZE);
+        return;
+    drive_g->type = DTYPE_RAMDISK;
+    dprintf(1, "Mapping CBFS floppy %s to addr %p\n", cbfs_filename(file), pos);
+    char *desc = znprintf(MAXDESCSIZE, "Ramdisk [%s]", cbfs_filename(file));
+    boot_add_floppy(drive_g, desc, -1);
 }
 
 static int
diff --git a/src/usb-msc.c b/src/usb-msc.c
index 877ece4..d5fe7ba 100644
--- a/src/usb-msc.c
+++ b/src/usb-msc.c
@@ -139,16 +139,16 @@
  ****************************************************************/
 
 static int
-setup_drive_cdrom(struct disk_op_s *op)
+setup_drive_cdrom(struct disk_op_s *op, char *desc)
 {
     op->drive_g->blksize = CDROM_SECTOR_SIZE;
     op->drive_g->sectors = (u64)-1;
-    boot_add_cd(op->drive_g, -1);
+    boot_add_cd(op->drive_g, desc, -1);
     return 0;
 }
 
 static int
-setup_drive_hd(struct disk_op_s *op)
+setup_drive_hd(struct disk_op_s *op, char *desc)
 {
     struct cdbres_read_capacity info;
     int ret = cdb_read_capacity(op, &info);
@@ -159,7 +159,7 @@
     u32 blksize = ntohl(info.blksize), sectors = ntohl(info.sectors);
     if (blksize != DISK_SECTOR_SIZE) {
         if (blksize == CDROM_SECTOR_SIZE)
-            return setup_drive_cdrom(op);
+            return setup_drive_cdrom(op, desc);
         dprintf(1, "Unsupported USB MSC block size %d\n", blksize);
         return -1;
     }
@@ -168,7 +168,7 @@
     dprintf(1, "USB MSC blksize=%d sectors=%d\n", blksize, sectors);
 
     // Register with bcv system.
-    boot_add_hd(op->drive_g, -1);
+    boot_add_hd(op->drive_g, desc, -1);
 
     return 0;
 }
@@ -192,9 +192,8 @@
     }
 
     // Allocate drive structure.
-    char *desc = malloc_tmphigh(MAXDESCSIZE);
     struct usbdrive_s *udrive_g = malloc_fseg(sizeof(*udrive_g));
-    if (!udrive_g || !desc) {
+    if (!udrive_g) {
         warn_noalloc();
         goto fail;
     }
@@ -232,20 +231,22 @@
             , strtcpy(rev, data.rev, sizeof(rev))
             , pdt, removable);
     udrive_g->drive.removable = removable;
-    snprintf(desc, MAXDESCSIZE, "USB Drive %s %s %s", vendor, product, rev);
-    udrive_g->drive.desc = desc;
 
-    if (pdt == USB_MSC_TYPE_CDROM)
-        ret = setup_drive_cdrom(&dop);
-    else
-        ret = setup_drive_hd(&dop);
+    if (pdt == USB_MSC_TYPE_CDROM) {
+        char *desc = znprintf(MAXDESCSIZE, "DVD/CD [USB Drive %s %s %s]"
+                              , vendor, product, rev);
+        ret = setup_drive_cdrom(&dop, desc);
+    } else {
+        char *desc = znprintf(MAXDESCSIZE, "USB Drive %s %s %s"
+                              , vendor, product, rev);
+        ret = setup_drive_hd(&dop, desc);
+    }
     if (ret)
         goto fail;
 
     return 0;
 fail:
     dprintf(1, "Unable to configure USB MSC device.\n");
-    free(desc);
     free(udrive_g);
     return -1;
 }
diff --git a/src/util.h b/src/util.h
index f5b9446..7102c27 100644
--- a/src/util.h
+++ b/src/util.h
@@ -237,6 +237,8 @@
     __attribute__ ((format (printf, 1, 2)));
 int snprintf(char *str, size_t size, const char *fmt, ...)
     __attribute__ ((format (printf, 3, 4)));
+char * znprintf(size_t size, const char *fmt, ...)
+    __attribute__ ((format (printf, 2, 3)));
 void __dprintf(const char *fmt, ...)
     __attribute__ ((format (printf, 1, 2)));
 void __debug_enter(struct bregs *regs, const char *fname);
diff --git a/src/virtio-blk.c b/src/virtio-blk.c
index 6b49164..bd9e2ad 100644
--- a/src/virtio-blk.c
+++ b/src/virtio-blk.c
@@ -101,10 +101,9 @@
 {
     dprintf(1, "found virtio-blk at %x:%x\n", pci_bdf_to_bus(bdf),
             pci_bdf_to_dev(bdf));
-    char *desc = malloc_tmphigh(MAXDESCSIZE);
     struct virtiodrive_s *vdrive_g = malloc_fseg(sizeof(*vdrive_g));
     struct vring_virtqueue *vq = memalign_low(PAGE_SIZE, sizeof(*vq));
-    if (!vdrive_g || !desc || !vq) {
+    if (!vdrive_g || !vq) {
         warn_noalloc();
         goto fail;
     }
@@ -151,11 +150,10 @@
     vdrive_g->drive.pchs.cylinders = cfg.cylinders;
     vdrive_g->drive.pchs.heads = cfg.heads;
     vdrive_g->drive.pchs.spt = cfg.sectors;
-    snprintf(desc, MAXDESCSIZE, "Virtio disk PCI:%x:%x",
-             pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf));
-    vdrive_g->drive.desc = desc;
+    char *desc = znprintf(MAXDESCSIZE, "Virtio disk PCI:%x:%x",
+                          pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf));
 
-    boot_add_hd(&vdrive_g->drive, bootprio_find_pci_device(bdf));
+    boot_add_hd(&vdrive_g->drive, desc, bootprio_find_pci_device(bdf));
 
     vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
                   VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK);
@@ -163,7 +161,6 @@
 
 fail:
     free(vdrive_g);
-    free(desc);
     free(vq);
 }