Commit 28c5af54c661e73e5596918fa67a22b5e87c2022

Authored by j_mayer
1 parent aba9ee87

More generic boot devices specification, allowing more devices to be specified

and avoiding per-target hardcoded limitations.
The machine implementations can then check if the given devices match the
actual hardware implementation and firmware API.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3577 c046a42c-6fe2-441c-8c8c-71466251a162
@@ -173,6 +173,7 @@ static int boot_device2nibble(char boot_device) @@ -173,6 +173,7 @@ static int boot_device2nibble(char boot_device)
173 static void cmos_init(int ram_size, const char *boot_device, BlockDriverState **hd_table) 173 static void cmos_init(int ram_size, const char *boot_device, BlockDriverState **hd_table)
174 { 174 {
175 RTCState *s = rtc_state; 175 RTCState *s = rtc_state;
  176 + int nbds, bds[3] = { 0, };
176 int val; 177 int val;
177 int fd0, fd1, nb; 178 int fd0, fd1, nb;
178 int i; 179 int i;
@@ -202,11 +203,22 @@ static void cmos_init(int ram_size, const char *boot_device, BlockDriverState ** @@ -202,11 +203,22 @@ static void cmos_init(int ram_size, const char *boot_device, BlockDriverState **
202 rtc_set_memory(s, 0x35, val >> 8); 203 rtc_set_memory(s, 0x35, val >> 8);
203 204
204 /* set boot devices, and disable floppy signature check if requested */ 205 /* set boot devices, and disable floppy signature check if requested */
205 - rtc_set_memory(s, 0x3d,  
206 - boot_device2nibble(boot_device[1]) << 4 |  
207 - boot_device2nibble(boot_device[0]) );  
208 - rtc_set_memory(s, 0x38,  
209 - boot_device2nibble(boot_device[2]) << 4 | (fd_bootchk ? 0x0 : 0x1)); 206 +#define PC_MAX_BOOT_DEVICES 3
  207 + nbds = strlen(boot_device);
  208 + if (nbds > PC_MAX_BOOT_DEVICES) {
  209 + fprintf(stderr, "Too many boot devices for PC\n");
  210 + exit(1);
  211 + }
  212 + for (i = 0; i < nbds; i++) {
  213 + bds[i] = boot_device2nibble(boot_device[i]);
  214 + if (bds[i] == 0) {
  215 + fprintf(stderr, "Invalid boot device for PC: '%c'\n",
  216 + boot_device[i]);
  217 + exit(1);
  218 + }
  219 + }
  220 + rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]);
  221 + rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ? 0x0 : 0x1));
210 222
211 /* floppy type */ 223 /* floppy type */
212 224
hw/ppc_chrp.c
@@ -74,7 +74,7 @@ static void ppc_core99_init (int ram_size, int vga_ram_size, @@ -74,7 +74,7 @@ static void ppc_core99_init (int ram_size, int vga_ram_size,
74 qemu_irq *dummy_irq; 74 qemu_irq *dummy_irq;
75 int pic_mem_index, dbdma_mem_index, cuda_mem_index; 75 int pic_mem_index, dbdma_mem_index, cuda_mem_index;
76 int ide_mem_index[2]; 76 int ide_mem_index[2];
77 - int ppc_boot_device = boot_device[0]; 77 + int ppc_boot_device;
78 78
79 linux_boot = (kernel_filename != NULL); 79 linux_boot = (kernel_filename != NULL);
80 80
@@ -175,6 +175,19 @@ static void ppc_core99_init (int ram_size, int vga_ram_size, @@ -175,6 +175,19 @@ static void ppc_core99_init (int ram_size, int vga_ram_size,
175 kernel_size = 0; 175 kernel_size = 0;
176 initrd_base = 0; 176 initrd_base = 0;
177 initrd_size = 0; 177 initrd_size = 0;
  178 + ppc_boot_device = '\0';
  179 + /* We consider that NewWorld PowerMac never have any floppy drive
  180 + * For now, OHW cannot boot from the network.
  181 + */
  182 + for (i = 0; i < boot_device[i] != '\0'; i++) {
  183 + ppc_boot_device = boot_device[i];
  184 + if (ppc_boot_device >= 'c' && ppc_boot_device <= 'f')
  185 + break;
  186 + }
  187 + if (ppc_boot_device == '\0') {
  188 + fprintf(stderr, "No valid boot device for Mac99 machine\n");
  189 + exit(1);
  190 + }
178 } 191 }
179 192
180 isa_mem_base = 0x80000000; 193 isa_mem_base = 0x80000000;
hw/ppc_oldworld.c
@@ -113,7 +113,7 @@ static void ppc_heathrow_init (int ram_size, int vga_ram_size, @@ -113,7 +113,7 @@ static void ppc_heathrow_init (int ram_size, int vga_ram_size,
113 int vga_bios_size, bios_size; 113 int vga_bios_size, bios_size;
114 qemu_irq *dummy_irq; 114 qemu_irq *dummy_irq;
115 int pic_mem_index, nvram_mem_index, dbdma_mem_index, cuda_mem_index; 115 int pic_mem_index, nvram_mem_index, dbdma_mem_index, cuda_mem_index;
116 - int ppc_boot_device = boot_device[0]; 116 + int ppc_boot_device;
117 117
118 linux_boot = (kernel_filename != NULL); 118 linux_boot = (kernel_filename != NULL);
119 119
@@ -212,6 +212,25 @@ static void ppc_heathrow_init (int ram_size, int vga_ram_size, @@ -212,6 +212,25 @@ static void ppc_heathrow_init (int ram_size, int vga_ram_size,
212 kernel_size = 0; 212 kernel_size = 0;
213 initrd_base = 0; 213 initrd_base = 0;
214 initrd_size = 0; 214 initrd_size = 0;
  215 + ppc_boot_device = '\0';
  216 + for (i = 0; i < boot_device[i] != '\0'; i++) {
  217 + ppc_boot_device = boot_device[i];
  218 + /* TOFIX: for now, the second IDE channel is not properly
  219 + * emulated. The Mac floppy disk are not emulated.
  220 + * For now, OHW cannot boot from the network.
  221 + */
  222 +#if 0
  223 + if (ppc_boot_device >= 'a' && ppc_boot_device <= 'f')
  224 + break;
  225 +#else
  226 + if (ppc_boot_device >= 'c' && ppc_boot_device <= 'd')
  227 + break;
  228 +#endif
  229 + }
  230 + if (ppc_boot_device == '\0') {
  231 + fprintf(stderr, "No valid boot device for Mac99 machine\n");
  232 + exit(1);
  233 + }
215 } 234 }
216 235
217 isa_mem_base = 0x80000000; 236 isa_mem_base = 0x80000000;
@@ -272,7 +291,7 @@ static void ppc_heathrow_init (int ram_size, int vga_ram_size, @@ -272,7 +291,7 @@ static void ppc_heathrow_init (int ram_size, int vga_ram_size,
272 pmac_format_nvram_partition(nvr, 0x2000); 291 pmac_format_nvram_partition(nvr, 0x2000);
273 292
274 dbdma_init(&dbdma_mem_index); 293 dbdma_init(&dbdma_mem_index);
275 - 294 +
276 macio_init(pci_bus, 0x0017, 1, pic_mem_index, dbdma_mem_index, 295 macio_init(pci_bus, 0x0017, 1, pic_mem_index, dbdma_mem_index,
277 cuda_mem_index, nvr, 0, NULL); 296 cuda_mem_index, nvr, 0, NULL);
278 297
hw/ppc_prep.c
@@ -521,7 +521,8 @@ CPUReadMemoryFunc *PPC_prep_io_read[] = { @@ -521,7 +521,8 @@ CPUReadMemoryFunc *PPC_prep_io_read[] = {
521 #define NVRAM_SIZE 0x2000 521 #define NVRAM_SIZE 0x2000
522 522
523 /* PowerPC PREP hardware initialisation */ 523 /* PowerPC PREP hardware initialisation */
524 -static void ppc_prep_init (int ram_size, int vga_ram_size, const char *boot_device, 524 +static void ppc_prep_init (int ram_size, int vga_ram_size,
  525 + const char *boot_device,
525 DisplayState *ds, const char **fd_filename, 526 DisplayState *ds, const char **fd_filename,
526 int snapshot, const char *kernel_filename, 527 int snapshot, const char *kernel_filename,
527 const char *kernel_cmdline, 528 const char *kernel_cmdline,
@@ -538,7 +539,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, const char *boot_devi @@ -538,7 +539,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, const char *boot_devi
538 uint32_t kernel_base, kernel_size, initrd_base, initrd_size; 539 uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
539 PCIBus *pci_bus; 540 PCIBus *pci_bus;
540 qemu_irq *i8259; 541 qemu_irq *i8259;
541 - int ppc_boot_device = boot_device[0]; 542 + int ppc_boot_device;
542 543
543 sysctrl = qemu_mallocz(sizeof(sysctrl_t)); 544 sysctrl = qemu_mallocz(sizeof(sysctrl_t));
544 if (sysctrl == NULL) 545 if (sysctrl == NULL)
@@ -611,6 +612,17 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, const char *boot_devi @@ -611,6 +612,17 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, const char *boot_devi
611 kernel_size = 0; 612 kernel_size = 0;
612 initrd_base = 0; 613 initrd_base = 0;
613 initrd_size = 0; 614 initrd_size = 0;
  615 + ppc_boot_device = '\0';
  616 + /* For now, OHW cannot boot from the network. */
  617 + for (i = 0; i < boot_device[i] != '\0'; i++) {
  618 + ppc_boot_device = boot_device[i];
  619 + if (ppc_boot_device >= 'a' && ppc_boot_device <= 'f')
  620 + break;
  621 + }
  622 + if (ppc_boot_device == '\0') {
  623 + fprintf(stderr, "No valid boot device for Mac99 machine\n");
  624 + exit(1);
  625 + }
614 } 626 }
615 627
616 isa_mem_base = 0xc0000000; 628 isa_mem_base = 0xc0000000;
@@ -162,12 +162,6 @@ static DisplayState display_state; @@ -162,12 +162,6 @@ static DisplayState display_state;
162 int nographic; 162 int nographic;
163 const char* keyboard_layout = NULL; 163 const char* keyboard_layout = NULL;
164 int64_t ticks_per_sec; 164 int64_t ticks_per_sec;
165 -#if defined(TARGET_I386)  
166 -#define MAX_BOOT_DEVICES 3  
167 -#else  
168 -#define MAX_BOOT_DEVICES 1  
169 -#endif  
170 -static char boot_device[MAX_BOOT_DEVICES + 1];  
171 int ram_size; 165 int ram_size;
172 int pit_min_timer_count = 0; 166 int pit_min_timer_count = 0;
173 int nb_nics; 167 int nb_nics;
@@ -7587,14 +7581,16 @@ int main(int argc, char **argv) @@ -7587,14 +7581,16 @@ int main(int argc, char **argv)
7587 int use_gdbstub; 7581 int use_gdbstub;
7588 const char *gdbstub_port; 7582 const char *gdbstub_port;
7589 #endif 7583 #endif
  7584 + uint32_t boot_devices_bitmap = 0;
7590 int i, cdrom_index, pflash_index; 7585 int i, cdrom_index, pflash_index;
7591 - int snapshot, linux_boot; 7586 + int snapshot, linux_boot, net_boot;
7592 const char *initrd_filename; 7587 const char *initrd_filename;
7593 const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD]; 7588 const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
7594 const char *pflash_filename[MAX_PFLASH]; 7589 const char *pflash_filename[MAX_PFLASH];
7595 const char *sd_filename; 7590 const char *sd_filename;
7596 const char *mtd_filename; 7591 const char *mtd_filename;
7597 const char *kernel_filename, *kernel_cmdline; 7592 const char *kernel_filename, *kernel_cmdline;
  7593 + const char *boot_devices = "";
7598 DisplayState *ds = &display_state; 7594 DisplayState *ds = &display_state;
7599 int cyls, heads, secs, translation; 7595 int cyls, heads, secs, translation;
7600 char net_clients[MAX_NET_CLIENTS][256]; 7596 char net_clients[MAX_NET_CLIENTS][256];
@@ -7846,20 +7842,34 @@ int main(int argc, char **argv) @@ -7846,20 +7842,34 @@ int main(int argc, char **argv)
7846 } 7842 }
7847 break; 7843 break;
7848 case QEMU_OPTION_boot: 7844 case QEMU_OPTION_boot:
7849 - if (strlen(optarg) > MAX_BOOT_DEVICES) {  
7850 - fprintf(stderr, "qemu: too many boot devices\n");  
7851 - exit(1);  
7852 - }  
7853 - strncpy(boot_device, optarg, MAX_BOOT_DEVICES);  
7854 -#if defined(TARGET_SPARC) || defined(TARGET_I386)  
7855 -#define BOOTCHARS "acdn"  
7856 -#else  
7857 -#define BOOTCHARS "acd"  
7858 -#endif  
7859 - if (strlen(boot_device) != strspn(boot_device, BOOTCHARS)) {  
7860 - fprintf(stderr, "qemu: invalid boot device "  
7861 - "sequence '%s'\n", boot_device);  
7862 - exit(1); 7845 + boot_devices = optarg;
  7846 + /* We just do some generic consistency checks */
  7847 + {
  7848 + /* Could easily be extended to 64 devices if needed */
  7849 + const unsigned char *p;
  7850 +
  7851 + boot_devices_bitmap = 0;
  7852 + for (p = boot_devices; *p != '\0'; p++) {
  7853 + /* Allowed boot devices are:
  7854 + * a b : floppy disk drives
  7855 + * c ... f : IDE disk drives
  7856 + * g ... m : machine implementation dependant drives
  7857 + * n ... p : network devices
  7858 + * It's up to each machine implementation to check
  7859 + * if the given boot devices match the actual hardware
  7860 + * implementation and firmware features.
  7861 + */
  7862 + if (*p < 'a' || *p > 'q') {
  7863 + fprintf(stderr, "Invalid boot device '%c'\n", *p);
  7864 + exit(1);
  7865 + }
  7866 + if (boot_devices_bitmap & (1 << (*p - 'a'))) {
  7867 + fprintf(stderr,
  7868 + "Boot device '%c' was given twice\n",*p);
  7869 + exit(1);
  7870 + }
  7871 + boot_devices_bitmap |= 1 << (*p - 'a');
  7872 + }
7863 } 7873 }
7864 break; 7874 break;
7865 case QEMU_OPTION_fda: 7875 case QEMU_OPTION_fda:
@@ -8243,23 +8253,23 @@ int main(int argc, char **argv) @@ -8243,23 +8253,23 @@ int main(int argc, char **argv)
8243 kqemu_allowed = 0; 8253 kqemu_allowed = 0;
8244 #endif 8254 #endif
8245 linux_boot = (kernel_filename != NULL); 8255 linux_boot = (kernel_filename != NULL);
8246 -  
8247 - if (!linux_boot &&  
8248 - (!strchr(boot_device, 'n')) && 8256 + net_boot = (boot_devices_bitmap >> ('n' - 'a')) && 0xF;
  8257 +
  8258 + /* XXX: this should not be: some embedded targets just have flash */
  8259 + if (!linux_boot && net_boot == 0 &&
8249 hd_filename[0] == '\0' && 8260 hd_filename[0] == '\0' &&
8250 (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') && 8261 (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
8251 fd_filename[0] == '\0') 8262 fd_filename[0] == '\0')
8252 help(1); 8263 help(1);
8253 8264
8254 /* boot to floppy or the default cd if no hard disk defined yet */ 8265 /* boot to floppy or the default cd if no hard disk defined yet */
8255 - if (!boot_device[0]) { 8266 + if (!boot_devices[0]) {
8256 if (hd_filename[0] != '\0') 8267 if (hd_filename[0] != '\0')
8257 - boot_device[0] = 'c'; 8268 + boot_devices = "c";
8258 else if (fd_filename[0] != '\0') 8269 else if (fd_filename[0] != '\0')
8259 - boot_device[0] = 'a'; 8270 + boot_devices = "a";
8260 else 8271 else
8261 - boot_device[0] = 'd';  
8262 - boot_device[1] = 0; 8272 + boot_devices = "d";
8263 } 8273 }
8264 setvbuf(stdout, NULL, _IOLBF, 0); 8274 setvbuf(stdout, NULL, _IOLBF, 0);
8265 8275
@@ -8299,20 +8309,28 @@ int main(int argc, char **argv) @@ -8299,20 +8309,28 @@ int main(int argc, char **argv)
8299 } 8309 }
8300 8310
8301 #ifdef TARGET_I386 8311 #ifdef TARGET_I386
8302 - if (strchr(boot_device, 'n')) {  
8303 - for (i = 0; i < nb_nics; i++) { 8312 + /* XXX: this should be moved in the PC machine instanciation code */
  8313 + if (net_boot != 0) {
  8314 + int netroms = 0;
  8315 + for (i = 0; i < nb_nics && i < 4; i++) {
8304 const char *model = nd_table[i].model; 8316 const char *model = nd_table[i].model;
8305 char buf[1024]; 8317 char buf[1024];
8306 - if (model == NULL)  
8307 - model = "ne2k_pci";  
8308 - snprintf(buf, sizeof(buf), "%s/pxe-%s.bin", bios_dir, model);  
8309 - if (get_image_size(buf) > 0) {  
8310 - option_rom[nb_option_roms] = strdup(buf);  
8311 - nb_option_roms++;  
8312 - break;  
8313 - } 8318 + if (net_boot & (1 << i)) {
  8319 + if (model == NULL)
  8320 + model = "ne2k_pci";
  8321 + snprintf(buf, sizeof(buf), "%s/pxe-%s.bin", bios_dir, model);
  8322 + if (get_image_size(buf) > 0) {
  8323 + if (nb_option_roms >= MAX_OPTION_ROMS) {
  8324 + fprintf(stderr, "Too many option ROMs\n");
  8325 + exit(1);
  8326 + }
  8327 + option_rom[nb_option_roms] = strdup(buf);
  8328 + nb_option_roms++;
  8329 + netroms++;
  8330 + }
  8331 + }
8314 } 8332 }
8315 - if (i == nb_nics) { 8333 + if (netroms == 0) {
8316 fprintf(stderr, "No valid PXE rom found for network device\n"); 8334 fprintf(stderr, "No valid PXE rom found for network device\n");
8317 exit(1); 8335 exit(1);
8318 } 8336 }
@@ -8492,7 +8510,7 @@ int main(int argc, char **argv) @@ -8492,7 +8510,7 @@ int main(int argc, char **argv)
8492 } 8510 }
8493 } 8511 }
8494 8512
8495 - machine->init(ram_size, vga_ram_size, boot_device, 8513 + machine->init(ram_size, vga_ram_size, boot_devices,
8496 ds, fd_filename, snapshot, 8514 ds, fd_filename, snapshot,
8497 kernel_filename, kernel_cmdline, initrd_filename, cpu_model); 8515 kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
8498 8516