Skip to contentSkip to conversation

set boot sequence from command line

PATCH In review Dan Kenigsberg 7 participants 8 messages Oct 24, 2007 – Oct 25, 2007

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 set boot sequence from command line

Real PCs try to boot from a CD, then try the hard drive, and finally go to the network. And they let their owner change that order. This patch lets Qemu do the same with "-boot dcn".

I'll be happy to hear comments about it,

Dan.

hw/an5206.c +1 -1
index 94ecccb..2134184 100644
@@ -27,7 +27,7 @@ void DMA_run (void)
 
 /* Board init.  */
 
-static void an5206_init(int ram_size, int vga_ram_size, int boot_device,
+static void an5206_init(int ram_size, int vga_ram_size, char *boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
hw/mcf5208.c +1 -1
index 993a686..19689ba 100644
@@ -197,7 +197,7 @@ static void mcf5208_sys_init(qemu_irq *pic)
     }
 }
 
-static void mcf5208evb_init(int ram_size, int vga_ram_size, int boot_device,
+static void mcf5208evb_init(int ram_size, int vga_ram_size, char *boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
hw/palm.c +1 -1
index 623fcd6..971ff37 100644
@@ -61,7 +61,7 @@ static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
 {
 }
 
-static void palmte_init(int ram_size, int vga_ram_size, int boot_device,
+static void palmte_init(int ram_size, int vga_ram_size, char *boot_device,
                 DisplayState *ds, const char **fd_filename, int snapshot,
                 const char *kernel_filename, const char *kernel_cmdline,
                 const char *initrd_filename, const char *cpu_model)
hw/pc.c +27 -22

80 lines not on this page · raw message

hw/ppc.c +2 -2
index 742d3de..d1bc943 100644
@@ -1347,7 +1347,7 @@ uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
 
 int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
                           const unsigned char *arch,
-                          uint32_t RAM_size, int boot_device,
+                          uint32_t RAM_size, char *boot_device,
                           uint32_t kernel_image, uint32_t kernel_size,
                           const char *cmdline,
                           uint32_t initrd_image, uint32_t initrd_size,
@@ -1362,7 +1362,7 @@ int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
     NVRAM_set_word(nvram,   0x14, NVRAM_size);
     NVRAM_set_string(nvram, 0x20, arch, 16);
     NVRAM_set_lword(nvram,  0x30, RAM_size);
-    NVRAM_set_byte(nvram,   0x34, boot_device);
+    NVRAM_set_byte(nvram,   0x34, boot_device[0]);
     NVRAM_set_lword(nvram,  0x38, kernel_image);
     NVRAM_set_lword(nvram,  0x3C, kernel_size);
     if (cmdline) {
hw/ppc_chrp.c +4 -4
index f53c85b..64c0fd1 100644
@@ -300,7 +300,7 @@ void pmac_format_nvram_partition (uint8_t *buf, int len)
 }
 
 /* PowerPC CHRP hardware initialisation */
-static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
+static void ppc_chrp_init (int ram_size, int vga_ram_size, char *boot_device,
                            DisplayState *ds, const char **fd_filename,
                            int snapshot,
                            const char *kernel_filename,
@@ -405,7 +405,7 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
             initrd_base = 0;
             initrd_size = 0;
         }
-        boot_device = 'm';
+        boot_device[0] = 'm';
     } else {
         kernel_base = 0;
         kernel_size = 0;
@@ -571,7 +571,7 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
     register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
 }
 
-static void ppc_core99_init (int ram_size, int vga_ram_size, int boot_device,
+static void ppc_core99_init (int ram_size, int vga_ram_size, char *boot_device,
                              DisplayState *ds, const char **fd_filename,
                              int snapshot,
                              const char *kernel_filename,
@@ -585,7 +585,7 @@ static void ppc_core99_init (int ram_size, int vga_ram_size, int boot_device,
                   initrd_filename, cpu_model, 0);
 }
 
-static void ppc_heathrow_init (int ram_size, int vga_ram_size, int boot_device,
+static void ppc_heathrow_init (int ram_size, int vga_ram_size, char *boot_device,
                                DisplayState *ds, const char **fd_filename,
                                int snapshot,
                                const char *kernel_filename,
hw/ppc_prep.c +2 -2
index 2c4b242..96bfde5 100644
@@ -518,7 +518,7 @@ CPUReadMemoryFunc *PPC_prep_io_read[] = {
 #define NVRAM_SIZE        0x2000
 
 /* PowerPC PREP hardware initialisation */
-static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
+static void ppc_prep_init (int ram_size, int vga_ram_size, char *boot_device,
                            DisplayState *ds, const char **fd_filename,
                            int snapshot, const char *kernel_filename,
                            const char *kernel_cmdline,
@@ -600,7 +600,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
             initrd_base = 0;
             initrd_size = 0;
         }
-        boot_device = 'm';
+        boot_device[0] = 'm';
     } else {
         kernel_base = 0;
         kernel_size = 0;
hw/realview.c +1 -1
index 375f78a..3acc96f 100644
@@ -12,7 +12,7 @@
 
 /* Board init.  */
 
-static void realview_init(int ram_size, int vga_ram_size, int boot_device,
+static void realview_init(int ram_size, int vga_ram_size, char *boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
hw/sun4m.c +6 -6
index a12aec9..7481eef 100644
@@ -158,7 +158,7 @@ static void nvram_finish_partition (m48t59_t *nvram, uint32_t start,
 extern int nographic;
 
 static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
-                       int boot_device, uint32_t RAM_size,
+                       char *boot_device, uint32_t RAM_size,
                        uint32_t kernel_size,
                        int width, int height, int depth,
                        int machine_id)
@@ -175,7 +175,7 @@ static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
     m48t59_write(nvram, 0x2E, 0);
     m48t59_write(nvram, 0x2F, nographic & 0xff);
     nvram_set_lword(nvram,  0x30, RAM_size);
-    m48t59_write(nvram, 0x34, boot_device & 0xff);
+    m48t59_write(nvram, 0x34, boot_device[0] & 0xff);
     nvram_set_lword(nvram,  0x38, KERNEL_LOAD_ADDR);
     nvram_set_lword(nvram,  0x3C, kernel_size);
     if (cmdline) {
@@ -408,7 +408,7 @@ static void *sun4m_hw_init(const struct hwdef *hwdef, int RAM_size,
     return nvram;
 }
 
-static void sun4m_load_kernel(long vram_size, int RAM_size, int boot_device,
+static void sun4m_load_kernel(long vram_size, int RAM_size, char *boot_device,
                               const char *kernel_filename,
                               const char *kernel_cmdline,
                               const char *initrd_filename,
@@ -548,7 +548,7 @@ static const struct hwdef hwdefs[] = {
     },
 };
 
-static void sun4m_common_init(int RAM_size, int boot_device, DisplayState *ds,
+static void sun4m_common_init(int RAM_size, char *boot_device, DisplayState *ds,
                               const char *kernel_filename, const char *kernel_cmdline,
                               const char *initrd_filename, const char *cpu_model,
                               unsigned int machine, int max_ram)
@@ -569,7 +569,7 @@ static void sun4m_common_init(int RAM_size, int boot_device, DisplayState *ds,
 }
 
 /* SPARCstation 5 hardware initialisation */
-static void ss5_init(int RAM_size, int vga_ram_size, int boot_device,
+static void ss5_init(int RAM_size, int vga_ram_size, char *boot_device,
                        DisplayState *ds, const char **fd_filename, int snapshot,
                        const char *kernel_filename, const char *kernel_cmdline,
                        const char *initrd_filename, const char *cpu_model)
@@ -582,7 +582,7 @@ static void ss5_init(int RAM_size, int vga_ram_size, int boot_device,
 }
 
 /* SPARCstation 10 hardware initialisation */
-static void ss10_init(int RAM_size, int vga_ram_size, int boot_device,
+static void ss10_init(int RAM_size, int vga_ram_size, char *boot_device,
                             DisplayState *ds, const char **fd_filename, int snapshot,
                             const char *kernel_filename, const char *kernel_cmdline,
                             const char *initrd_filename, const char *cpu_model)
hw/sun4u.c +3 -3
index bac0ebf..2c1b598 100644
@@ -203,7 +203,7 @@ extern int nographic;
 
 int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
                           const unsigned char *arch,
-                          uint32_t RAM_size, int boot_device,
+                          uint32_t RAM_size, char *boot_device,
                           uint32_t kernel_image, uint32_t kernel_size,
                           const char *cmdline,
                           uint32_t initrd_image, uint32_t initrd_size,
@@ -221,7 +221,7 @@ int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
     NVRAM_set_string(nvram, 0x20, arch, 16);
     NVRAM_set_byte(nvram,   0x2f, nographic & 0xff);
     NVRAM_set_lword(nvram,  0x30, RAM_size);
-    NVRAM_set_byte(nvram,   0x34, boot_device);
+    NVRAM_set_byte(nvram,   0x34, boot_device[0]);
     NVRAM_set_lword(nvram,  0x38, kernel_image);
     NVRAM_set_lword(nvram,  0x3C, kernel_size);
     if (cmdline) {
@@ -331,7 +331,7 @@ static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 static fdctrl_t *floppy_controller;
 
 /* Sun4u hardware initialisation */
-static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
+static void sun4u_init(int ram_size, int vga_ram_size, char *boot_device,
              DisplayState *ds, const char **fd_filename, int snapshot,
              const char *kernel_filename, const char *kernel_cmdline,
              const char *initrd_filename, const char *cpu_model)
vl.c +19 -13
index 6d8fe35..be0e06a 100644
@@ -161,7 +161,7 @@ static DisplayState display_state;
 int nographic;
 const char* keyboard_layout = NULL;
 int64_t ticks_per_sec;
-int boot_device = 'c';
+static char *boot_device;
 int ram_size;
 int pit_min_timer_count = 0;
 int nb_nics;
@@ -7788,14 +7788,19 @@ int main(int argc, char **argv)
                 }
                 break;
             case QEMU_OPTION_boot:
-                boot_device = optarg[0];
-                if (boot_device != 'a' &&
+                if (strlen(optarg) > 3) {
+                    fprintf(stderr, "qemu: too many boot devices\n");
+                    exit(1);
+                }
+                boot_device = strdup(optarg);
+                if (!strchr(boot_device, 'a') &&
 #if defined(TARGET_SPARC) || defined(TARGET_I386)
 		    // Network boot
-		    boot_device != 'n' &&
+		    !strchr(boot_device, 'n') &&
 #endif
-                    boot_device != 'c' && boot_device != 'd') {
-                    fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device);
+		    !strchr(boot_device, 'c') &&
+		    !strchr(boot_device, 'd')) {
+                    fprintf(stderr, "qemu: invalid boot device sequence '%s'\n", boot_device);
                     exit(1);
                 }
                 break;
@@ -8146,20 +8151,21 @@ int main(int argc, char **argv)
     linux_boot = (kernel_filename != NULL);
 
     if (!linux_boot &&
-        boot_device != 'n' &&
+        (!boot_device || !strchr(boot_device, 'n')) &&
         hd_filename[0] == '\0' &&
         (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
         fd_filename[0] == '\0')
         help(1);
 
     /* boot to floppy or the default cd if no hard disk defined yet */
-    if (hd_filename[0] == '\0' && boot_device == 'c') {
-        if (fd_filename[0] != '\0')
-            boot_device = 'a';
+    if (!boot_device) {
+        if (hd_filename[0] != '\0')
+            boot_device = "c";
+        else if (fd_filename[0] != '\0')
+            boot_device = "a";
         else
-            boot_device = 'd';
+            boot_device = "d";
     }
-
     setvbuf(stdout, NULL, _IOLBF, 0);
 
     init_timers();
@@ -8198,7 +8204,7 @@ int main(int argc, char **argv)
     }
 
 #ifdef TARGET_I386
-    if (boot_device == 'n') {
+    if (strchr(boot_device, 'n')) {
 	for (i = 0; i < nb_nics; i++) {
 	    const char *model = nd_table[i].model;
 	    char buf[1024];
vl.h +2 -2
index adf6004..4751f2f 100644
@@ -725,7 +725,7 @@ void path_combine(char *dest, int dest_size,
 #ifndef QEMU_TOOL
 
 typedef void QEMUMachineInitFunc(int ram_size, int vga_ram_size,
-                                 int boot_device,
+                                 char *boot_device,
              DisplayState *ds, const char **fd_filename, int snapshot,
              const char *kernel_filename, const char *kernel_cmdline,
              const char *initrd_filename, const char *cpu_model);
@@ -1339,7 +1339,7 @@ void NVRAM_set_crc (m48t59_t *nvram, uint32_t addr,
                     uint32_t start, uint32_t count);
 int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
                           const unsigned char *arch,
-                          uint32_t RAM_size, int boot_device,
+                          uint32_t RAM_size, char *boot_device,
                           uint32_t kernel_image, uint32_t kernel_size,
                           const char *cmdline,
                           uint32_t initrd_image, uint32_t initrd_size,
#1 lore raw
Quoted 5 lines · Dan Kenigsberg

Real PCs try to boot from a CD, then try the hard drive, and finally go to the network. And they let their owner change that order. This patch lets Qemu do the same with "-boot dcn".

I'll be happy to hear comments about it,

Personally, I think it's a very good idea.

Laurent

Signature · 2 lines
---------------- [email protected]  -----------------
"Given enough eyeballs, all bugs are shallow" E. S. Raymond
#2 lore raw
In reply to Dan Kenigsberg
Quoted 6 lines · Dan Kenigsberg

Real PCs try to boot from a CD, then try the hard drive, and finally go to the network. And they let their owner change that order. This patch lets Qemu do the same with "-boot dcn".

I'll be happy to hear comments about it,

Looks good to me. I wrote a very similar patch recently but haven't gotten around to submitting it. I'm very eager to see this included!

Regards,

Anthony Liguori

Quoted 417 lines

Dan.

hw/an5206.c +1 -1
index 94ecccb..2134184 100644
@@ -27,7 +27,7 @@ void DMA_run (void)
 
 /* Board init.  */
 
-static void an5206_init(int ram_size, int vga_ram_size, int boot_device,
+static void an5206_init(int ram_size, int vga_ram_size, char *boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
hw/mcf5208.c +1 -1
index 993a686..19689ba 100644
@@ -197,7 +197,7 @@ static void mcf5208_sys_init(qemu_irq *pic)
     }
 }
 
-static void mcf5208evb_init(int ram_size, int vga_ram_size, int boot_device,
+static void mcf5208evb_init(int ram_size, int vga_ram_size, char *boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
hw/palm.c +1 -1
index 623fcd6..971ff37 100644
@@ -61,7 +61,7 @@ static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
 {
 }
 
-static void palmte_init(int ram_size, int vga_ram_size, int boot_device,
+static void palmte_init(int ram_size, int vga_ram_size, char *boot_device,
                 DisplayState *ds, const char **fd_filename, int snapshot,
                 const char *kernel_filename, const char *kernel_cmdline,
                 const char *initrd_filename, const char *cpu_model)
hw/pc.c +27 -22
index a0c824f..3c552ff 100644
@@ -152,8 +152,25 @@ static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd)
     rtc_set_memory(s, info_ofs + 8, sectors);
 }
 
+/* convert boot_device letter to something recognizable by the bios */
+static int boot_device2nible(char boot_device)
+{
+    switch(boot_device) {
+    case 'a':
+    case 'b':
+        return 0x01; /* floppy boot */
+    case 'c':
+        return 0x02; /* hard drive boot */
+    case 'd':
+        return 0x03; /* CD-ROM boot */
+    case 'n':
+        return 0x04; /* Network boot */
+    }
+    return 0;
+}
+
 /* hd_table must contain 4 block drivers */
-static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table)
+static void cmos_init(int ram_size, char *boot_device, BlockDriverState **hd_table)
 {
     RTCState *s = rtc_state;
     int val;
@@ -184,24 +201,12 @@ static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table
     rtc_set_memory(s, 0x34, val);
     rtc_set_memory(s, 0x35, val >> 8);
 
-    switch(boot_device) {
-    case 'a':
-    case 'b':
-        rtc_set_memory(s, 0x3d, 0x01); /* floppy boot */
-        if (!fd_bootchk)
-            rtc_set_memory(s, 0x38, 0x01); /* disable signature check */
-        break;
-    default:
-    case 'c':
-        rtc_set_memory(s, 0x3d, 0x02); /* hard drive boot */
-        break;
-    case 'd':
-        rtc_set_memory(s, 0x3d, 0x03); /* CD-ROM boot */
-        break;
-    case 'n':
-        rtc_set_memory(s, 0x3d, 0x04); /* Network boot */
-        break;
-    }
+    /* set boot devices, and disable floppy signature check if requested */
+    rtc_set_memory(s, 0x3d,
+            boot_device2nible(boot_device[1]) << 4 |
+            boot_device2nible(boot_device[0]) );
+    rtc_set_memory(s, 0x38,
+            boot_device2nible(boot_device[2]) << 4 | (fd_bootchk ? 0x0 : 0x1));
 
     /* floppy type */
 
@@ -663,7 +668,7 @@ static void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic)
 }
 
 /* PC hardware initialisation */
-static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
+static void pc_init1(int ram_size, int vga_ram_size, char *boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename,
@@ -947,7 +952,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
 #endif
 }
 
-static void pc_init_pci(int ram_size, int vga_ram_size, int boot_device,
+static void pc_init_pci(int ram_size, int vga_ram_size, char *boot_device,
                         DisplayState *ds, const char **fd_filename,
                         int snapshot,
                         const char *kernel_filename,
@@ -961,7 +966,7 @@ static void pc_init_pci(int ram_size, int vga_ram_size, int boot_device,
              initrd_filename, 1, cpu_model);
 }
 
-static void pc_init_isa(int ram_size, int vga_ram_size, int boot_device,
+static void pc_init_isa(int ram_size, int vga_ram_size, char *boot_device,
                         DisplayState *ds, const char **fd_filename,
                         int snapshot,
                         const char *kernel_filename,
hw/ppc.c +2 -2
index 742d3de..d1bc943 100644
@@ -1347,7 +1347,7 @@ uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
 
 int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
                           const unsigned char *arch,
-                          uint32_t RAM_size, int boot_device,
+                          uint32_t RAM_size, char *boot_device,
                           uint32_t kernel_image, uint32_t kernel_size,
                           const char *cmdline,
                           uint32_t initrd_image, uint32_t initrd_size,
@@ -1362,7 +1362,7 @@ int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
     NVRAM_set_word(nvram,   0x14, NVRAM_size);
     NVRAM_set_string(nvram, 0x20, arch, 16);
     NVRAM_set_lword(nvram,  0x30, RAM_size);
-    NVRAM_set_byte(nvram,   0x34, boot_device);
+    NVRAM_set_byte(nvram,   0x34, boot_device[0]);
     NVRAM_set_lword(nvram,  0x38, kernel_image);
     NVRAM_set_lword(nvram,  0x3C, kernel_size);
     if (cmdline) {
hw/ppc_chrp.c +4 -4
index f53c85b..64c0fd1 100644
@@ -300,7 +300,7 @@ void pmac_format_nvram_partition (uint8_t *buf, int len)
 }
 
 /* PowerPC CHRP hardware initialisation */
-static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
+static void ppc_chrp_init (int ram_size, int vga_ram_size, char *boot_device,
                            DisplayState *ds, const char **fd_filename,
                            int snapshot,
                            const char *kernel_filename,
@@ -405,7 +405,7 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
             initrd_base = 0;
             initrd_size = 0;
         }
-        boot_device = 'm';
+        boot_device[0] = 'm';
     } else {
         kernel_base = 0;
         kernel_size = 0;
@@ -571,7 +571,7 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
     register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
 }
 
-static void ppc_core99_init (int ram_size, int vga_ram_size, int boot_device,
+static void ppc_core99_init (int ram_size, int vga_ram_size, char *boot_device,
                              DisplayState *ds, const char **fd_filename,
                              int snapshot,
                              const char *kernel_filename,
@@ -585,7 +585,7 @@ static void ppc_core99_init (int ram_size, int vga_ram_size, int boot_device,
                   initrd_filename, cpu_model, 0);
 }
 
-static void ppc_heathrow_init (int ram_size, int vga_ram_size, int boot_device,
+static void ppc_heathrow_init (int ram_size, int vga_ram_size, char *boot_device,
                                DisplayState *ds, const char **fd_filename,
                                int snapshot,
                                const char *kernel_filename,
hw/ppc_prep.c +2 -2
index 2c4b242..96bfde5 100644
@@ -518,7 +518,7 @@ CPUReadMemoryFunc *PPC_prep_io_read[] = {
 #define NVRAM_SIZE        0x2000
 
 /* PowerPC PREP hardware initialisation */
-static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
+static void ppc_prep_init (int ram_size, int vga_ram_size, char *boot_device,
                            DisplayState *ds, const char **fd_filename,
                            int snapshot, const char *kernel_filename,
                            const char *kernel_cmdline,
@@ -600,7 +600,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
             initrd_base = 0;
             initrd_size = 0;
         }
-        boot_device = 'm';
+        boot_device[0] = 'm';
     } else {
         kernel_base = 0;
         kernel_size = 0;
hw/realview.c +1 -1
index 375f78a..3acc96f 100644
@@ -12,7 +12,7 @@
 
 /* Board init.  */
 
-static void realview_init(int ram_size, int vga_ram_size, int boot_device,
+static void realview_init(int ram_size, int vga_ram_size, char *boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
hw/sun4m.c +6 -6
index a12aec9..7481eef 100644
@@ -158,7 +158,7 @@ static void nvram_finish_partition (m48t59_t *nvram, uint32_t start,
 extern int nographic;
 
 static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
-                       int boot_device, uint32_t RAM_size,
+                       char *boot_device, uint32_t RAM_size,
                        uint32_t kernel_size,
                        int width, int height, int depth,
                        int machine_id)
@@ -175,7 +175,7 @@ static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
     m48t59_write(nvram, 0x2E, 0);
     m48t59_write(nvram, 0x2F, nographic & 0xff);
     nvram_set_lword(nvram,  0x30, RAM_size);
-    m48t59_write(nvram, 0x34, boot_device & 0xff);
+    m48t59_write(nvram, 0x34, boot_device[0] & 0xff);
     nvram_set_lword(nvram,  0x38, KERNEL_LOAD_ADDR);
     nvram_set_lword(nvram,  0x3C, kernel_size);
     if (cmdline) {
@@ -408,7 +408,7 @@ static void *sun4m_hw_init(const struct hwdef *hwdef, int RAM_size,
     return nvram;
 }
 
-static void sun4m_load_kernel(long vram_size, int RAM_size, int boot_device,
+static void sun4m_load_kernel(long vram_size, int RAM_size, char *boot_device,
                               const char *kernel_filename,
                               const char *kernel_cmdline,
                               const char *initrd_filename,
@@ -548,7 +548,7 @@ static const struct hwdef hwdefs[] = {
     },
 };
 
-static void sun4m_common_init(int RAM_size, int boot_device, DisplayState *ds,
+static void sun4m_common_init(int RAM_size, char *boot_device, DisplayState *ds,
                               const char *kernel_filename, const char *kernel_cmdline,
                               const char *initrd_filename, const char *cpu_model,
                               unsigned int machine, int max_ram)
@@ -569,7 +569,7 @@ static void sun4m_common_init(int RAM_size, int boot_device, DisplayState *ds,
 }
 
 /* SPARCstation 5 hardware initialisation */
-static void ss5_init(int RAM_size, int vga_ram_size, int boot_device,
+static void ss5_init(int RAM_size, int vga_ram_size, char *boot_device,
                        DisplayState *ds, const char **fd_filename, int snapshot,
                        const char *kernel_filename, const char *kernel_cmdline,
                        const char *initrd_filename, const char *cpu_model)
@@ -582,7 +582,7 @@ static void ss5_init(int RAM_size, int vga_ram_size, int boot_device,
 }
 
 /* SPARCstation 10 hardware initialisation */
-static void ss10_init(int RAM_size, int vga_ram_size, int boot_device,
+static void ss10_init(int RAM_size, int vga_ram_size, char *boot_device,
                             DisplayState *ds, const char **fd_filename, int snapshot,
                             const char *kernel_filename, const char *kernel_cmdline,
                             const char *initrd_filename, const char *cpu_model)
hw/sun4u.c +3 -3
index bac0ebf..2c1b598 100644
@@ -203,7 +203,7 @@ extern int nographic;
 
 int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
                           const unsigned char *arch,
-                          uint32_t RAM_size, int boot_device,
+                          uint32_t RAM_size, char *boot_device,
                           uint32_t kernel_image, uint32_t kernel_size,
                           const char *cmdline,
                           uint32_t initrd_image, uint32_t initrd_size,
@@ -221,7 +221,7 @@ int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
     NVRAM_set_string(nvram, 0x20, arch, 16);
     NVRAM_set_byte(nvram,   0x2f, nographic & 0xff);
     NVRAM_set_lword(nvram,  0x30, RAM_size);
-    NVRAM_set_byte(nvram,   0x34, boot_device);
+    NVRAM_set_byte(nvram,   0x34, boot_device[0]);
     NVRAM_set_lword(nvram,  0x38, kernel_image);
     NVRAM_set_lword(nvram,  0x3C, kernel_size);
     if (cmdline) {
@@ -331,7 +331,7 @@ static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 static fdctrl_t *floppy_controller;
 
 /* Sun4u hardware initialisation */
-static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
+static void sun4u_init(int ram_size, int vga_ram_size, char *boot_device,
              DisplayState *ds, const char **fd_filename, int snapshot,
              const char *kernel_filename, const char *kernel_cmdline,
              const char *initrd_filename, const char *cpu_model)
vl.c +19 -13
index 6d8fe35..be0e06a 100644
@@ -161,7 +161,7 @@ static DisplayState display_state;
 int nographic;
 const char* keyboard_layout = NULL;
 int64_t ticks_per_sec;
-int boot_device = 'c';
+static char *boot_device;
 int ram_size;
 int pit_min_timer_count = 0;
 int nb_nics;
@@ -7788,14 +7788,19 @@ int main(int argc, char **argv)
                 }
                 break;
             case QEMU_OPTION_boot:
-                boot_device = optarg[0];
-                if (boot_device != 'a' &&
+                if (strlen(optarg) > 3) {
+                    fprintf(stderr, "qemu: too many boot devices\n");
+                    exit(1);
+                }
+                boot_device = strdup(optarg);
+                if (!strchr(boot_device, 'a') &&
 #if defined(TARGET_SPARC) || defined(TARGET_I386)
 		    // Network boot
-		    boot_device != 'n' &&
+		    !strchr(boot_device, 'n') &&
 #endif
-                    boot_device != 'c' && boot_device != 'd') {
-                    fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device);
+		    !strchr(boot_device, 'c') &&
+		    !strchr(boot_device, 'd')) {
+                    fprintf(stderr, "qemu: invalid boot device sequence '%s'\n", boot_device);
                     exit(1);
                 }
                 break;
@@ -8146,20 +8151,21 @@ int main(int argc, char **argv)
     linux_boot = (kernel_filename != NULL);
 
     if (!linux_boot &&
-        boot_device != 'n' &&
+        (!boot_device || !strchr(boot_device, 'n')) &&
         hd_filename[0] == '\0' &&
         (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
         fd_filename[0] == '\0')
         help(1);
 
     /* boot to floppy or the default cd if no hard disk defined yet */
-    if (hd_filename[0] == '\0' && boot_device == 'c') {
-        if (fd_filename[0] != '\0')
-            boot_device = 'a';
+    if (!boot_device) {
+        if (hd_filename[0] != '\0')
+            boot_device = "c";
+        else if (fd_filename[0] != '\0')
+            boot_device = "a";
         else
-            boot_device = 'd';
+            boot_device = "d";
     }
-
     setvbuf(stdout, NULL, _IOLBF, 0);
 
     init_timers();
@@ -8198,7 +8204,7 @@ int main(int argc, char **argv)
     }
 
 #ifdef TARGET_I386
-    if (boot_device == 'n') {
+    if (strchr(boot_device, 'n')) {
 	for (i = 0; i < nb_nics; i++) {
 	    const char *model = nd_table[i].model;
 	    char buf[1024];
vl.h +2 -2
index adf6004..4751f2f 100644
@@ -725,7 +725,7 @@ void path_combine(char *dest, int dest_size,
 #ifndef QEMU_TOOL
 
 typedef void QEMUMachineInitFunc(int ram_size, int vga_ram_size,
-                                 int boot_device,
+                                 char *boot_device,
              DisplayState *ds, const char **fd_filename, int snapshot,
              const char *kernel_filename, const char *kernel_cmdline,
              const char *initrd_filename, const char *cpu_model);
@@ -1339,7 +1339,7 @@ void NVRAM_set_crc (m48t59_t *nvram, uint32_t addr,
                     uint32_t start, uint32_t count);
 int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
                           const unsigned char *arch,
-                          uint32_t RAM_size, int boot_device,
+                          uint32_t RAM_size, char *boot_device,
                           uint32_t kernel_image, uint32_t kernel_size,
                           const char *cmdline,
                           uint32_t initrd_image, uint32_t initrd_size,
#3 lore raw
Quoted 10 lines · Anthony Liguori
Quoted 6 lines · Dan Kenigsberg

Real PCs try to boot from a CD, then try the hard drive, and finally go to the network. And they let their owner change that order. This patch lets Qemu do the same with "-boot dcn".

I'll be happy to hear comments about it,

Looks good to me. I wrote a very similar patch recently but haven't gotten around to submitting it. I'm very eager to see this included!

A more or less identical patch to this has been in Xen's fork of QEMU for quite a while & works nicely, so it'd definitely be good to have this in the main QEMU codebase.

Dan.

Signature · 4 lines
|=- Red Hat, Engineering, Emerging Technologies, Boston.  +1 978 392 2496 -=|
|=-           Perl modules: http://search.cpan.org/~danberr/              -=|
|=-               Projects: http://freshmeat.net/~danielpb/               -=|
|=-  GnuPG: 7D3B9505   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505  -=| 
#4 lore raw
In reply to Dan Kenigsberg
Quoted 2 lines · Dan Kenigsberg

Real PCs try to boot from a CD, then try the hard drive, and finally go to the network. And they let their owner change that order.

With the difference that on real PCs this is controlled by the BIOS menu rather than a hardware switch, but the latter seems more convenient for qemu.

Quoted 11 lines

This patch lets Qemu do the same with "-boot dcn".

I'll be happy to hear comments about it,

Dan.

hw/an5206.c +0 -0
index 94ecccb..2134184 100644

hw/an5206.c void DMA_run (void) · line 33

Quoted 8 lines
hw/an5206.c +1 -1
@@ -27,7 +27,7 @@ void DMA_run (void)
 
 /* Board init.  */
 
-static void an5206_init(int ram_size, int vga_ram_size, int boot_device,
+static void an5206_init(int ram_size, int vga_ram_size, char *boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)

BTW, it may be a good idea to pass all these values (maybe except ds) as a single struct, for purely practical reasons.
Regards

#5 lore raw
Quoted 22 lines · andrzej zaborowski
Quoted 2 lines · Dan Kenigsberg

Real PCs try to boot from a CD, then try the hard drive, and finally go to the network. And they let their owner change that order.

With the difference that on real PCs this is controlled by the BIOS menu rather than a hardware switch, but the latter seems more convenient for qemu.

Quoted 14 lines

This patch lets Qemu do the same with "-boot dcn".

I'll be happy to hear comments about it,

Dan.

hw/an5206.c +0 -0
index 94ecccb..2134184 100644
@@ -27,7 +27,7 @@ void DMA_run (void)
 
 /* Board init.  */
 
Quoted 9 lines

hw/an5206.c void DMA_run (void) · line 33

Quoted 5 lines
hw/an5206.c +1 -1
-static void an5206_init(int ram_size, int vga_ram_size, int boot_device,
+static void an5206_init(int ram_size, int vga_ram_size, char *boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)

BTW, it may be a good idea to pass all these values (maybe except ds) as a single struct, for purely practical reasons.
Regards

Maybe the use of several structure may be better:
- one could be used to describe the kernel boot (with kernel_filename, kernel_cmdline, initrd_filename) and could be NULL
- one for the hardware emulation parameters (ram_size, vga_ram_sze, cpu_model)
- one for the emulation parameters if needed (snapshot, ds...)
...
It may be more consistent than use a single structure melting misc stuff that are not directly related.

One remark about the submited patch:
why are the boot order table limited to 3 elements ? There are at least 4 choices available today (floppy, disk, CDROM, network) and maybe more in the future for some architecture (refering to the curently emulated
hardware: 2 floppies, 4 IDE devices, <n> network devices, SCSI storages, ...).

I guess it's not a so good idea to override the boot_device table in the machine init routines. Imho, it would better be passed as a const char * argument. For the PowerPC part, there could be a local int boot_device variable that would be initialized to the first argument of the table. And this would not change the NVRAM initialisation API: if this API need to support more than one boot device in the future, it will have to be completelly reworked (for other reasons too), then I would suggest to be conservative and do not change this API at all.

Signature · 2 lines
J. Mayer <[email protected]>
Never organized
#6 lore raw
In reply to Dan Kenigsberg

It is perhaps not the best idea to read behind the end of the boot_device string. It would be safer to declare boot_device as 'static char boot_device[4]' and use a strncpy.

Bernhard

Quoted 22 lines
hw/pc.c +6 -0
index a0c824f..3c552ff 100644
+    /* set boot devices, and disable floppy signature check if requested */
+    rtc_set_memory(s, 0x3d,
+            boot_device2nible(boot_device[1]) << 4 |
+            boot_device2nible(boot_device[0]) );
+    rtc_set_memory(s, 0x38,
+            boot_device2nible(boot_device[2]) << 4 | (fd_bootchk ? 0x0 : 0x1));
 
     /* floppy type */
vl.c +6 -0
index 6d8fe35..be0e06a 100644
+                if (strlen(optarg) > 3) {
+                    fprintf(stderr, "qemu: too many boot devices\n");
+                    exit(1);
+                }
+                boot_device = strdup(optarg);
+                if (!strchr(boot_device, 'a') &&
#7 lore raw

Re: [Qemu-devel] [Patch] set boot sequence from command line - Take 2

Quoted 8 lines · Bernhard Kauer

It is perhaps not the best idea to read behind the end of the boot_device string. It would be safer to declare boot_device as 'static char boot_device[4]' and use a strncpy.

Bernhard

Thanks for the good catch! (and to others who commented)

In this "take" has the following changes:
1. QEMUMachineInitFunc uses const char *boot_device
2. correct spelling of `nibble'
3. avoid touching PPC_NVRAM_set_params() API needlessly
4. allocate boot_device statically
5. define MAX_BOOT_DEVICES clearly according to the TARGET. Only three devices are supoorted by the i386 bios
6. reject the boot string if it includes a single unrecognized letter

Dan.

hw/an5206.c +1 -1
index 94ecccb..d9931df 100644
@@ -27,7 +27,7 @@ void DMA_run (void)
 
 /* Board init.  */
 
-static void an5206_init(int ram_size, int vga_ram_size, int boot_device,
+static void an5206_init(int ram_size, int vga_ram_size, const char *boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
hw/mcf5208.c +1 -1
index 993a686..8c4181b 100644
@@ -197,7 +197,7 @@ static void mcf5208_sys_init(qemu_irq *pic)
     }
 }
 
-static void mcf5208evb_init(int ram_size, int vga_ram_size, int boot_device,
+static void mcf5208evb_init(int ram_size, int vga_ram_size, const char *boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
hw/palm.c +1 -1
index 623fcd6..3101e9e 100644
@@ -61,7 +61,7 @@ static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
 {
 }
 
-static void palmte_init(int ram_size, int vga_ram_size, int boot_device,
+static void palmte_init(int ram_size, int vga_ram_size, const char *boot_device,
                 DisplayState *ds, const char **fd_filename, int snapshot,
                 const char *kernel_filename, const char *kernel_cmdline,
                 const char *initrd_filename, const char *cpu_model)
hw/pc.c +27 -22

80 lines not on this page · raw message

hw/ppc_chrp.c +6 -5
index f53c85b..6fbde7f 100644
@@ -300,7 +300,7 @@ void pmac_format_nvram_partition (uint8_t *buf, int len)
 }
 
 /* PowerPC CHRP hardware initialisation */
-static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
+static void ppc_chrp_init (int ram_size, int vga_ram_size, const char *boot_device,
                            DisplayState *ds, const char **fd_filename,
                            int snapshot,
                            const char *kernel_filename,
@@ -322,6 +322,7 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
     const char *arch_name;
     int vga_bios_size, bios_size;
     qemu_irq *dummy_irq;
+    int ppc_boot_device = boot_device[0];
 
     linux_boot = (kernel_filename != NULL);
 
@@ -405,7 +406,7 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
             initrd_base = 0;
             initrd_size = 0;
         }
-        boot_device = 'm';
+        ppc_boot_device = 'm';
     } else {
         kernel_base = 0;
         kernel_size = 0;
@@ -558,7 +559,7 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
     if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
         graphic_depth = 15;
 
-    PPC_NVRAM_set_params(nvram, NVRAM_SIZE, arch_name, ram_size, boot_device,
+    PPC_NVRAM_set_params(nvram, NVRAM_SIZE, arch_name, ram_size, ppc_boot_device,
                          kernel_base, kernel_size,
                          kernel_cmdline,
                          initrd_base, initrd_size,
@@ -571,7 +572,7 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
     register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
 }
 
-static void ppc_core99_init (int ram_size, int vga_ram_size, int boot_device,
+static void ppc_core99_init (int ram_size, int vga_ram_size, const char *boot_device,
                              DisplayState *ds, const char **fd_filename,
                              int snapshot,
                              const char *kernel_filename,
@@ -585,7 +586,7 @@ static void ppc_core99_init (int ram_size, int vga_ram_size, int boot_device,
                   initrd_filename, cpu_model, 0);
 }
 
-static void ppc_heathrow_init (int ram_size, int vga_ram_size, int boot_device,
+static void ppc_heathrow_init (int ram_size, int vga_ram_size, const char *boot_device,
                                DisplayState *ds, const char **fd_filename,
                                int snapshot,
                                const char *kernel_filename,
hw/ppc_prep.c +4 -3
index 2c4b242..7a92edf 100644
@@ -518,7 +518,7 @@ CPUReadMemoryFunc *PPC_prep_io_read[] = {
 #define NVRAM_SIZE        0x2000
 
 /* PowerPC PREP hardware initialisation */
-static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
+static void ppc_prep_init (int ram_size, int vga_ram_size, const char *boot_device,
                            DisplayState *ds, const char **fd_filename,
                            int snapshot, const char *kernel_filename,
                            const char *kernel_cmdline,
@@ -535,6 +535,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
     ppc_def_t *def;
     PCIBus *pci_bus;
     qemu_irq *i8259;
+    int ppc_boot_device = boot_device[0];
 
     sysctrl = qemu_mallocz(sizeof(sysctrl_t));
     if (sysctrl == NULL)
@@ -600,7 +601,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
             initrd_base = 0;
             initrd_size = 0;
         }
-        boot_device = 'm';
+        ppc_boot_device = 'm';
     } else {
         kernel_base = 0;
         kernel_size = 0;
@@ -689,7 +690,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
     sysctrl->nvram = nvram;
 
     /* Initialise NVRAM */
-    PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
+    PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "PREP", ram_size, ppc_boot_device,
                          kernel_base, kernel_size,
                          kernel_cmdline,
                          initrd_base, initrd_size,
hw/realview.c +1 -1
index 375f78a..9582c92 100644
@@ -12,7 +12,7 @@
 
 /* Board init.  */
 
-static void realview_init(int ram_size, int vga_ram_size, int boot_device,
+static void realview_init(int ram_size, int vga_ram_size, const char *boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename, const char *cpu_model)
hw/sun4m.c +6 -6
index a12aec9..e5511cd 100644
@@ -158,7 +158,7 @@ static void nvram_finish_partition (m48t59_t *nvram, uint32_t start,
 extern int nographic;
 
 static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
-                       int boot_device, uint32_t RAM_size,
+                       const char *boot_device, uint32_t RAM_size,
                        uint32_t kernel_size,
                        int width, int height, int depth,
                        int machine_id)
@@ -175,7 +175,7 @@ static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
     m48t59_write(nvram, 0x2E, 0);
     m48t59_write(nvram, 0x2F, nographic & 0xff);
     nvram_set_lword(nvram,  0x30, RAM_size);
-    m48t59_write(nvram, 0x34, boot_device & 0xff);
+    m48t59_write(nvram, 0x34, boot_device[0] & 0xff);
     nvram_set_lword(nvram,  0x38, KERNEL_LOAD_ADDR);
     nvram_set_lword(nvram,  0x3C, kernel_size);
     if (cmdline) {
@@ -408,7 +408,7 @@ static void *sun4m_hw_init(const struct hwdef *hwdef, int RAM_size,
     return nvram;
 }
 
-static void sun4m_load_kernel(long vram_size, int RAM_size, int boot_device,
+static void sun4m_load_kernel(long vram_size, int RAM_size, const char *boot_device,
                               const char *kernel_filename,
                               const char *kernel_cmdline,
                               const char *initrd_filename,
@@ -548,7 +548,7 @@ static const struct hwdef hwdefs[] = {
     },
 };
 
-static void sun4m_common_init(int RAM_size, int boot_device, DisplayState *ds,
+static void sun4m_common_init(int RAM_size, const char *boot_device, DisplayState *ds,
                               const char *kernel_filename, const char *kernel_cmdline,
                               const char *initrd_filename, const char *cpu_model,
                               unsigned int machine, int max_ram)
@@ -569,7 +569,7 @@ static void sun4m_common_init(int RAM_size, int boot_device, DisplayState *ds,
 }
 
 /* SPARCstation 5 hardware initialisation */
-static void ss5_init(int RAM_size, int vga_ram_size, int boot_device,
+static void ss5_init(int RAM_size, int vga_ram_size, const char *boot_device,
                        DisplayState *ds, const char **fd_filename, int snapshot,
                        const char *kernel_filename, const char *kernel_cmdline,
                        const char *initrd_filename, const char *cpu_model)
@@ -582,7 +582,7 @@ static void ss5_init(int RAM_size, int vga_ram_size, int boot_device,
 }
 
 /* SPARCstation 10 hardware initialisation */
-static void ss10_init(int RAM_size, int vga_ram_size, int boot_device,
+static void ss10_init(int RAM_size, int vga_ram_size, const char *boot_device,
                             DisplayState *ds, const char **fd_filename, int snapshot,
                             const char *kernel_filename, const char *kernel_cmdline,
                             const char *initrd_filename, const char *cpu_model)
hw/sun4u.c +2 -2
index bac0ebf..317ba74 100644
@@ -331,7 +331,7 @@ static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 static fdctrl_t *floppy_controller;
 
 /* Sun4u hardware initialisation */
-static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
+static void sun4u_init(int ram_size, int vga_ram_size, const char *boot_device,
              DisplayState *ds, const char **fd_filename, int snapshot,
              const char *kernel_filename, const char *kernel_cmdline,
              const char *initrd_filename, const char *cpu_model)
@@ -456,7 +456,7 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
     i8042_init(NULL/*1*/, NULL/*12*/, 0x60);
     floppy_controller = fdctrl_init(NULL/*6*/, 2, 0, 0x3f0, fd_table);
     nvram = m48t59_init(NULL/*8*/, 0, 0x0074, NVRAM_SIZE, 59);
-    sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", ram_size, boot_device,
+    sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", ram_size, boot_device[0],
                          KERNEL_LOAD_ADDR, kernel_size,
                          kernel_cmdline,
                          INITRD_LOAD_ADDR, initrd_size,
vl.c +25 -14
index 6d8fe35..9a34490 100644
@@ -161,7 +161,12 @@ static DisplayState display_state;
 int nographic;
 const char* keyboard_layout = NULL;
 int64_t ticks_per_sec;
-int boot_device = 'c';
+#if defined(TARGET_I386)
+#define MAX_BOOT_DEVICES 3
+#else
+#define MAX_BOOT_DEVICES 1
+#endif
+static char boot_device[MAX_BOOT_DEVICES + 1];
 int ram_size;
 int pit_min_timer_count = 0;
 int nb_nics;
@@ -7788,14 +7793,18 @@ int main(int argc, char **argv)
                 }
                 break;
             case QEMU_OPTION_boot:
-                boot_device = optarg[0];
-                if (boot_device != 'a' &&
+                if (strlen(optarg) > MAX_BOOT_DEVICES) {
+                    fprintf(stderr, "qemu: too many boot devices\n");
+                    exit(1);
+                }
+                strncpy(boot_device, optarg, MAX_BOOT_DEVICES);
 #if defined(TARGET_SPARC) || defined(TARGET_I386)
-		    // Network boot
-		    boot_device != 'n' &&
+#define BOOTCHARS "acdn"
+#else
+#define BOOTCHARS "acd"
 #endif
-                    boot_device != 'c' && boot_device != 'd') {
-                    fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device);
+                if (strlen(boot_device) != strspn(boot_device, BOOTCHARS)) {
+                    fprintf(stderr, "qemu: invalid boot device sequence '%s'\n", boot_device);
                     exit(1);
                 }
                 break;
@@ -8146,20 +8155,22 @@ int main(int argc, char **argv)
     linux_boot = (kernel_filename != NULL);
 
     if (!linux_boot &&
-        boot_device != 'n' &&
+        (!strchr(boot_device, 'n')) &&
         hd_filename[0] == '\0' &&
         (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
         fd_filename[0] == '\0')
         help(1);
 
     /* boot to floppy or the default cd if no hard disk defined yet */
-    if (hd_filename[0] == '\0' && boot_device == 'c') {
-        if (fd_filename[0] != '\0')
-            boot_device = 'a';
+    if (!boot_device[0]) {
+        if (hd_filename[0] != '\0')
+            boot_device[0] = 'c';
+        else if (fd_filename[0] != '\0')
+            boot_device[0] = 'a';
         else
-            boot_device = 'd';
+            boot_device[0] = 'd';
+        boot_device[1] = 0;
     }
-
     setvbuf(stdout, NULL, _IOLBF, 0);
 
     init_timers();
@@ -8198,7 +8209,7 @@ int main(int argc, char **argv)
     }
 
 #ifdef TARGET_I386
-    if (boot_device == 'n') {
+    if (strchr(boot_device, 'n')) {
 	for (i = 0; i < nb_nics; i++) {
 	    const char *model = nd_table[i].model;
 	    char buf[1024];
vl.h +1 -1
index adf6004..390d221 100644
@@ -725,7 +725,7 @@ void path_combine(char *dest, int dest_size,
 #ifndef QEMU_TOOL
 
 typedef void QEMUMachineInitFunc(int ram_size, int vga_ram_size,
-                                 int boot_device,
+                                 const char *boot_device,
              DisplayState *ds, const char **fd_filename, int snapshot,
              const char *kernel_filename, const char *kernel_cmdline,
              const char *initrd_filename, const char *cpu_model);