/[dynamips]/upstream/dynamips-0.2.6-RC4/vm.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/dynamips-0.2.6-RC4/vm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (show annotations)
Sat Oct 6 16:08:03 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 18897 byte(s)
dynamips-0.2.6-RC4

1 /*
2 * Cisco 7200 (Predator) simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 *
5 * Virtual machine abstraction.
6 *
7 * TODO: IRQ Routing.
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <sys/types.h>
17 #include <assert.h>
18
19 #include "registry.h"
20 #include "device.h"
21 #include "pci_dev.h"
22 #include "pci_io.h"
23 #include "vm.h"
24 #include "dev_vtty.h"
25
26 #include ARCH_INC_FILE
27
28 #define DEBUG_VM 1
29
30 /* Type of VM file naming (0=use VM name, 1=use instance ID) */
31 int vm_file_naming_type = 0;
32
33 /* Initialize a VM object */
34 void vm_object_init(vm_obj_t *obj)
35 {
36 memset(obj,0,sizeof(*obj));
37 }
38
39 /* Add a VM object to an instance */
40 void vm_object_add(vm_instance_t *vm,vm_obj_t *obj)
41 {
42 obj->next = vm->vm_object_list;
43 obj->pprev = &vm->vm_object_list;
44
45 if (vm->vm_object_list)
46 vm->vm_object_list->pprev = &obj->next;
47
48 vm->vm_object_list = obj;
49 }
50
51 /* Remove a VM object from an instance */
52 void vm_object_remove(vm_instance_t *vm,vm_obj_t *obj)
53 {
54 if (obj->next)
55 obj->next->pprev = obj->pprev;
56 *(obj->pprev) = obj->next;
57
58 obj->shutdown(vm,obj->data);
59 }
60
61 /* Find an object given its name */
62 vm_obj_t *vm_object_find(vm_instance_t *vm,char *name)
63 {
64 vm_obj_t *obj;
65
66 for(obj=vm->vm_object_list;obj;obj=obj->next)
67 if (!strcmp(obj->name,name))
68 return obj;
69
70 return NULL;
71 }
72
73 /* Check that a mandatory object is present */
74 int vm_object_check(vm_instance_t *vm,char *name)
75 {
76 return(vm_object_find(vm,name) ? 0 : -1);
77 }
78
79 /* Shut down all objects of an instance */
80 void vm_object_free_list(vm_instance_t *vm)
81 {
82 vm_obj_t *obj,*next;
83
84 for(obj=vm->vm_object_list;obj;obj=next) {
85 next = obj->next;
86
87 if (obj->shutdown != NULL) {
88 #if DEBUG_VM
89 vm_log(vm,"VM_OBJECT","Shutdown of object \"%s\"\n",obj->name);
90 #endif
91 obj->shutdown(vm,obj->data);
92 }
93 }
94
95 vm->vm_object_list = NULL;
96 }
97
98 /* Dump the object list of an instance */
99 void vm_object_dump(vm_instance_t *vm)
100 {
101 vm_obj_t *obj;
102
103 printf("VM \"%s\" (%u) object list:\n",vm->name,vm->instance_id);
104
105 for(obj=vm->vm_object_list;obj;obj=obj->next) {
106 printf(" - %-15s [data=%p]\n",obj->name,obj->data);
107 }
108
109 printf("\n");
110 }
111
112 /* Get VM type */
113 char *vm_get_type(vm_instance_t *vm)
114 {
115 char *machine;
116
117 switch(vm->type) {
118 case VM_TYPE_C3600:
119 machine = "c3600";
120 break;
121 case VM_TYPE_C7200:
122 machine = "c7200";
123 break;
124 case VM_TYPE_C2691:
125 machine = "c2691";
126 break;
127 case VM_TYPE_C3725:
128 machine = "c3725";
129 break;
130 case VM_TYPE_C3745:
131 machine = "c3745";
132 break;
133 default:
134 machine = "unknown";
135 break;
136 }
137
138 return machine;
139 }
140
141 /* Get platform type */
142 char *vm_get_platform_type(vm_instance_t *vm)
143 {
144 char *machine;
145
146 switch(vm->type) {
147 case VM_TYPE_C3600:
148 machine = "C3600";
149 break;
150 case VM_TYPE_C7200:
151 machine = "C7200";
152 break;
153 case VM_TYPE_C2691:
154 machine = "C2691";
155 break;
156 case VM_TYPE_C3725:
157 machine = "C3725";
158 break;
159 case VM_TYPE_C3745:
160 machine = "C3745";
161 break;
162 default:
163 machine = "VM";
164 break;
165 }
166
167 return machine;
168 }
169
170 /* Get MAC address MSB */
171 u_int vm_get_mac_addr_msb(vm_instance_t *vm)
172 {
173 switch(vm->type) {
174 case VM_TYPE_C3600:
175 return(0xCC);
176
177 case VM_TYPE_C7200:
178 return(0xCA);
179
180 case VM_TYPE_C2691:
181 return(0xC0);
182
183 case VM_TYPE_C3725:
184 return(0xC2);
185
186 case VM_TYPE_C3745:
187 return(0xC4);
188
189 default:
190 return(0xC6);
191 }
192 }
193
194 /* Generate a filename for use by the instance */
195 char *vm_build_filename(vm_instance_t *vm,char *name)
196 {
197 char *filename,*machine;
198
199 machine = vm_get_type(vm);
200
201 switch(vm_file_naming_type) {
202 case 1:
203 filename = dyn_sprintf("%s_i%u_%s",machine,vm->instance_id,name);
204 break;
205 case 0:
206 default:
207 filename = dyn_sprintf("%s_%s_%s",machine,vm->name,name);
208 break;
209 }
210
211 assert(filename != NULL);
212 return filename;
213 }
214
215 /* Erase lock file */
216 void vm_release_lock(vm_instance_t *vm,int erase)
217 {
218 if (vm->lock_fd != NULL) {
219 fclose(vm->lock_fd);
220 vm->lock_fd = NULL;
221 }
222
223 if (vm->lock_file != NULL) {
224 if (erase)
225 unlink(vm->lock_file);
226 free(vm->lock_file);
227 vm->lock_file = NULL;
228 }
229 }
230
231 /* Check that an instance lock file doesn't already exist */
232 int vm_get_lock(vm_instance_t *vm)
233 {
234 char pid_str[32];
235 struct flock lock;
236
237 vm->lock_file = vm_build_filename(vm,"lock");
238
239 if (!(vm->lock_fd = fopen(vm->lock_file,"w"))) {
240 fprintf(stderr,"Unable to create lock file \"%s\".\n",vm->lock_file);
241 return(-1);
242 }
243
244 memset(&lock,0,sizeof(lock));
245 lock.l_type = F_WRLCK;
246 lock.l_whence = SEEK_SET;
247 lock.l_start = 0;
248 lock.l_len = 0;
249
250 if (fcntl(fileno(vm->lock_fd),F_SETLK,&lock) == -1) {
251 if (fcntl(fileno(vm->lock_fd),F_GETLK,&lock) == 0) {
252 snprintf(pid_str,sizeof(pid_str),"%ld",(long)lock.l_pid);
253 } else {
254 strcpy(pid_str,"unknown");
255 }
256
257 fprintf(stderr,
258 "\nAn emulator instance (PID %s) is already running with "
259 "identifier %u.\n"
260 "If this is not the case, please erase file \"%s\".\n\n",
261 pid_str,vm->instance_id,vm->lock_file);
262 vm_release_lock(vm,FALSE);
263 return(-1);
264 }
265
266 /* write the emulator PID */
267 fprintf(vm->lock_fd,"%ld\n",(u_long)getpid());
268 return(0);
269 }
270
271 /* Log a message */
272 void vm_flog(vm_instance_t *vm,char *module,char *format,va_list ap)
273 {
274 if (vm->log_fd)
275 m_flog(vm->log_fd,module,format,ap);
276 }
277
278 /* Log a message */
279 void vm_log(vm_instance_t *vm,char *module,char *format,...)
280 {
281 va_list ap;
282
283 va_start(ap,format);
284 vm_flog(vm,module,format,ap);
285 va_end(ap);
286 }
287
288 /* Close the log file */
289 int vm_close_log(vm_instance_t *vm)
290 {
291 if (vm->log_fd)
292 fclose(vm->log_fd);
293
294 free(vm->log_file);
295
296 vm->log_file = NULL;
297 vm->log_fd = NULL;
298 return(0);
299 }
300
301 /* Create the log file */
302 int vm_create_log(vm_instance_t *vm)
303 {
304 vm_close_log(vm);
305
306 if (!(vm->log_file = vm_build_filename(vm,"log.txt")))
307 return(-1);
308
309 if (!(vm->log_fd = fopen(vm->log_file,"w"))) {
310 fprintf(stderr,"VM %s: unable to create log file '%s'\n",
311 vm->name,vm->log_file);
312 free(vm->log_file);
313 vm->log_file = NULL;
314 return(-1);
315 }
316
317 return(0);
318 }
319
320 /* Error message */
321 void vm_error(vm_instance_t *vm,char *format,...)
322 {
323 char buffer[2048];
324 va_list ap;
325
326 va_start(ap,format);
327 vsnprintf(buffer,sizeof(buffer),format,ap);
328 va_end(ap);
329
330 fprintf(stderr,"%s '%s': %s",vm_get_platform_type(vm),vm->name,buffer);
331 }
332
333 /* Create a new VM instance */
334 vm_instance_t *vm_create(char *name,int instance_id,int machine_type)
335 {
336 vm_instance_t *vm;
337
338 if (!(vm = malloc(sizeof(*vm)))) {
339 fprintf(stderr,"VM %s: unable to create new instance!\n",name);
340 return NULL;
341 }
342
343 memset(vm,0,sizeof(*vm));
344 vm->instance_id = instance_id;
345 vm->type = machine_type;
346 vm->status = VM_STATUS_HALTED;
347 vm->jit_use = JIT_SUPPORT;
348 vm->vtty_con_type = VTTY_TYPE_TERM;
349 vm->vtty_aux_type = VTTY_TYPE_NONE;
350 vm->timer_irq_check_itv = VM_TIMER_IRQ_CHECK_ITV;
351
352 if (!(vm->name = strdup(name))) {
353 fprintf(stderr,"VM %s: unable to store instance name!\n",name);
354 goto err_name;
355 }
356
357 /* create lock file */
358 if (vm_get_lock(vm) == -1)
359 goto err_lock;
360
361 /* create log file */
362 if (vm_create_log(vm) == -1)
363 goto err_log;
364
365 if (registry_add(vm->name,OBJ_TYPE_VM,vm) == -1) {
366 fprintf(stderr,"VM: Unable to store instance '%s' in registry!\n",
367 vm->name);
368 goto err_reg_add;
369 }
370
371 return vm;
372
373 err_reg_add:
374 vm_close_log(vm);
375 err_log:
376 free(vm->lock_file);
377 err_lock:
378 free(vm->name);
379 err_name:
380 free(vm);
381 return NULL;
382 }
383
384 /*
385 * Shutdown hardware resources used by a VM.
386 * The CPU must have been stopped.
387 */
388 int vm_hardware_shutdown(vm_instance_t *vm)
389 {
390 int i;
391
392 if ((vm->status == VM_STATUS_HALTED) || !vm->cpu_group) {
393 vm_log(vm,"VM","trying to shutdown an inactive VM.\n");
394 return(-1);
395 }
396
397 vm_log(vm,"VM","shutdown procedure engaged.\n");
398
399 /* Mark the VM as halted */
400 vm->status = VM_STATUS_HALTED;
401
402 /* Disable NVRAM operations */
403 vm->nvram_extract_config = NULL;
404 vm->nvram_push_config = NULL;
405
406 /* Free the object list */
407 vm_object_free_list(vm);
408
409 /* Free resources used by PCI busses */
410 vm_log(vm,"VM","removing PCI busses.\n");
411 pci_io_data_remove(vm,vm->pci_io_space);
412 pci_bus_remove(vm->pci_bus[0]);
413 pci_bus_remove(vm->pci_bus[1]);
414 vm->pci_bus[0] = vm->pci_bus[1] = NULL;
415
416 /* Free the PCI bus pool */
417 for(i=0;i<VM_PCI_POOL_SIZE;i++) {
418 if (vm->pci_bus_pool[i] != NULL) {
419 pci_bus_remove(vm->pci_bus_pool[i]);
420 vm->pci_bus_pool[i] = NULL;
421 }
422 }
423
424 /* Delete the VTTY for Console and AUX ports */
425 vm_log(vm,"VM","deleting VTTY.\n");
426 vm_delete_vtty(vm);
427
428 /* Delete system CPU group */
429 vm_log(vm,"VM","deleting system CPUs.\n");
430 cpu_group_delete(vm->cpu_group);
431 vm->cpu_group = NULL;
432 vm->boot_cpu = NULL;
433
434 vm_log(vm,"VM","shutdown procedure completed.\n");
435 return(0);
436 }
437
438 /* Free resources used by a VM */
439 void vm_free(vm_instance_t *vm)
440 {
441 if (vm != NULL) {
442 /* Free hardware resources */
443 vm_hardware_shutdown(vm);
444
445 /* Close log file */
446 vm_close_log(vm);
447
448 /* Remove the lock file */
449 vm_release_lock(vm,TRUE);
450
451 /* Free various elements */
452 free(vm->ghost_ram_filename);
453 free(vm->sym_filename);
454 free(vm->ios_image);
455 free(vm->ios_config);
456 free(vm->rom_filename);
457 free(vm->name);
458 free(vm);
459 }
460 }
461
462 /* Get an instance given a name */
463 vm_instance_t *vm_acquire(char *name)
464 {
465 return(registry_find(name,OBJ_TYPE_VM));
466 }
467
468 /* Release a VM (decrement reference count) */
469 int vm_release(vm_instance_t *vm)
470 {
471 return(registry_unref(vm->name,OBJ_TYPE_VM));
472 }
473
474 /* Initialize RAM */
475 int vm_ram_init(vm_instance_t *vm,m_uint64_t paddr)
476 {
477 m_uint32_t len;
478
479 len = vm->ram_size * 1048576;
480
481 if (vm->ghost_status == VM_GHOST_RAM_USE)
482 return(dev_ram_ghost_init(vm,"ram",vm->ghost_ram_filename,paddr,len));
483
484 return(dev_ram_init(vm,"ram",vm->ram_mmap,
485 (vm->ghost_status != VM_GHOST_RAM_GENERATE),
486 vm->ghost_ram_filename,paddr,len));
487 }
488
489 /* Initialize VTTY */
490 int vm_init_vtty(vm_instance_t *vm)
491 {
492 /* Create Console and AUX ports */
493 vm->vtty_con = vtty_create(vm,"Console port",
494 vm->vtty_con_type,vm->vtty_con_tcp_port,
495 &vm->vtty_con_serial_option);
496
497 vm->vtty_aux = vtty_create(vm,"AUX port",
498 vm->vtty_aux_type,vm->vtty_aux_tcp_port,
499 &vm->vtty_aux_serial_option);
500 return(0);
501 }
502
503 /* Delete VTTY */
504 void vm_delete_vtty(vm_instance_t *vm)
505 {
506 vtty_delete(vm->vtty_con);
507 vtty_delete(vm->vtty_aux);
508 vm->vtty_con = vm->vtty_aux = NULL;
509 }
510
511 /* Bind a device to a virtual machine */
512 int vm_bind_device(vm_instance_t *vm,struct vdevice *dev)
513 {
514 struct vdevice **cur;
515 u_int i;
516
517 /*
518 * Add this device to the device array. The index in the device array
519 * is used by the MTS subsystem.
520 */
521 for(i=0;i<MIPS64_DEVICE_MAX;i++)
522 if (!vm->dev_array[i])
523 break;
524
525 if (i == MIPS64_DEVICE_MAX) {
526 fprintf(stderr,"VM%u: vm_bind_device: device table full.\n",
527 vm->instance_id);
528 return(-1);
529 }
530
531 vm->dev_array[i] = dev;
532 dev->id = i;
533
534 /*
535 * Add it to the linked-list (devices are ordered by physical addresses).
536 */
537 for(cur=&vm->dev_list;*cur;cur=&(*cur)->next)
538 if ((*cur)->phys_addr > dev->phys_addr)
539 break;
540
541 dev->next = *cur;
542 if (*cur) (*cur)->pprev = &dev->next;
543 dev->pprev = cur;
544 *cur = dev;
545 return(0);
546 }
547
548 /* Unbind a device from a virtual machine */
549 int vm_unbind_device(vm_instance_t *vm,struct vdevice *dev)
550 {
551 u_int i;
552
553 if (!dev->pprev)
554 return(-1);
555
556 /* Remove the device from the linked list */
557 if (dev->next)
558 dev->next->pprev = dev->pprev;
559
560 *(dev->pprev) = dev->next;
561
562 /* Remove the device from the device array */
563 for(i=0;i<MIPS64_DEVICE_MAX;i++)
564 if (vm->dev_array[i] == dev) {
565 vm->dev_array[i] = NULL;
566 break;
567 }
568
569 /* Clear device list info */
570 dev->next = NULL;
571 dev->pprev = NULL;
572 return(0);
573 }
574
575 /* Map a device at the specified physical address */
576 int vm_map_device(vm_instance_t *vm,struct vdevice *dev,m_uint64_t base_addr)
577 {
578 #if 0
579 /* Suspend VM activity */
580 vm_suspend(vm);
581
582 if (cpu_group_sync_state(vm->cpu_group) == -1) {
583 fprintf(stderr,"VM%u: unable to sync with system CPUs.\n",
584 vm->instance_id);
585 return(-1);
586 }
587 #endif
588
589 /* Unbind the device if it was already active */
590 vm_unbind_device(vm,dev);
591
592 /* Map the device at the new base address and rebuild MTS */
593 dev->phys_addr = base_addr;
594 vm_bind_device(vm,dev);
595 cpu_group_rebuild_mts(vm->cpu_group);
596
597 #if 0
598 vm_resume(vm);
599 #endif
600 return(0);
601 }
602
603 /* Set an IRQ for a VM */
604 void vm_set_irq(vm_instance_t *vm,u_int irq)
605 {
606 if (vm->boot_cpu->irq_disable) {
607 vm->boot_cpu->irq_pending = 0;
608 return;
609 }
610
611 /* TODO: IRQ routing */
612 mips64_set_irq(vm->boot_cpu,irq);
613
614 if (vm->boot_cpu->irq_idle_preempt[irq])
615 mips64_idle_break_wait(vm->boot_cpu);
616 }
617
618 /* Clear an IRQ for a VM */
619 void vm_clear_irq(vm_instance_t *vm,u_int irq)
620 {
621 /* TODO: IRQ routing */
622 mips64_clear_irq(vm->boot_cpu,irq);
623 }
624
625 /* Suspend a VM instance */
626 int vm_suspend(vm_instance_t *vm)
627 {
628 if (vm->status == VM_STATUS_RUNNING) {
629 cpu_group_save_state(vm->cpu_group);
630 cpu_group_set_state(vm->cpu_group,MIPS_CPU_SUSPENDED);
631 vm->status = VM_STATUS_SUSPENDED;
632 }
633 return(0);
634 }
635
636 /* Resume a VM instance */
637 int vm_resume(vm_instance_t *vm)
638 {
639 if (vm->status == VM_STATUS_SUSPENDED) {
640 cpu_group_restore_state(vm->cpu_group);
641 vm->status = VM_STATUS_RUNNING;
642 }
643 return(0);
644 }
645
646 /* Stop an instance */
647 int vm_stop(vm_instance_t *vm)
648 {
649 cpu_group_stop_all_cpu(vm->cpu_group);
650 vm->status = VM_STATUS_SHUTDOWN;
651 return(0);
652 }
653
654 /* Monitor an instance periodically */
655 void vm_monitor(vm_instance_t *vm)
656 {
657 while(vm->status != VM_STATUS_SHUTDOWN)
658 usleep(200000);
659 }
660
661 /* Open a VM file and map it in memory */
662 int vm_mmap_open_file(vm_instance_t *vm,char *name,
663 u_char **ptr,off_t *fsize)
664 {
665 char *filename;
666 int fd;
667
668 if (!(filename = vm_build_filename(vm,name))) {
669 fprintf(stderr,"vm_mmap_open_file: unable to create filename (%s)\n",
670 name);
671 return(-1);
672 }
673
674 if ((fd = memzone_open_file(filename,ptr,fsize)) == -1)
675 fprintf(stderr,"vm_mmap_open_file: unable to open file '%s' (%s)\n",
676 filename,strerror(errno));
677
678 free(filename);
679 return(fd);
680 }
681
682 /* Open/Create a VM file and map it in memory */
683 int vm_mmap_create_file(vm_instance_t *vm,char *name,size_t len,u_char **ptr)
684 {
685 char *filename;
686 int fd;
687
688 if (!(filename = vm_build_filename(vm,name))) {
689 fprintf(stderr,"vm_mmap_create_file: unable to create filename (%s)\n",
690 name);
691 return(-1);
692 }
693
694 if ((fd = memzone_create_file(filename,len,ptr)) == -1)
695 fprintf(stderr,"vm_mmap_create_file: unable to open file '%s' (%s)\n",
696 filename,strerror(errno));
697
698 free(filename);
699 return(fd);
700 }
701
702 /* Close a memory mapped file */
703 int vm_mmap_close_file(int fd,u_char *ptr,size_t len)
704 {
705 if (ptr != NULL)
706 munmap(ptr,len);
707
708 if (fd != -1)
709 close(fd);
710
711 return(0);
712 }
713
714 /* Save the Cisco IOS configuration from NVRAM */
715 int vm_ios_save_config(vm_instance_t *vm)
716 {
717 char *output;
718 int res;
719
720 if (!(output = vm_build_filename(vm,"ios_cfg.txt")))
721 return(-1);
722
723 res = vm_nvram_extract_config(vm,output);
724 free(output);
725 return(res);
726 }
727
728 /* Set Cisco IOS image to use */
729 int vm_ios_set_image(vm_instance_t *vm,char *ios_image)
730 {
731 char *str;
732
733 if (!(str = strdup(ios_image)))
734 return(-1);
735
736 if (vm->ios_image != NULL) {
737 free(vm->ios_image);
738 vm->ios_image = NULL;
739 }
740
741 vm->ios_image = str;
742 return(0);
743 }
744
745 /* Unset a Cisco IOS configuration file */
746 void vm_ios_unset_config(vm_instance_t *vm)
747 {
748 if (vm->ios_config != NULL) {
749 free(vm->ios_config);
750 vm->ios_config = NULL;
751 }
752 }
753
754 /* Set Cisco IOS configuration file to use */
755 int vm_ios_set_config(vm_instance_t *vm,char *ios_config)
756 {
757 char *str;
758
759 if (!(str = strdup(ios_config)))
760 return(-1);
761
762 vm_ios_unset_config(vm);
763 vm->ios_config = str;
764 return(0);
765 }
766
767 /* Extract IOS configuration from NVRAM and write it to a file */
768 int vm_nvram_extract_config(vm_instance_t *vm,char *filename)
769 {
770 char *cfg_buffer;
771 ssize_t cfg_len;
772 FILE *fd;
773
774 if (!vm->nvram_extract_config)
775 return(-1);
776
777 /* Extract the IOS configuration */
778 if (((cfg_len = vm->nvram_extract_config(vm,&cfg_buffer)) < 0) ||
779 (cfg_buffer == NULL))
780 return(-1);
781
782 /* Write configuration to the specified filename */
783 if (!(fd = fopen(filename,"w"))) {
784 vm_error(vm,"unable to create file '%s'\n",filename);
785 free(cfg_buffer);
786 return(-1);
787 }
788
789 fwrite(cfg_buffer,cfg_len,1,fd);
790
791 fclose(fd);
792 free(cfg_buffer);
793 return(0);
794 }
795
796 /* Read an IOS configuraton from a file and push it to NVRAM */
797 int vm_nvram_push_config(vm_instance_t *vm,char *filename)
798 {
799 char *cfg_buffer;
800 ssize_t len;
801 int res;
802
803 if (!vm->nvram_push_config)
804 return(-1);
805
806 /* Read configuration */
807 if (((len = m_read_file(filename,&cfg_buffer)) <= 0) || !cfg_buffer)
808 return(-1);
809
810 /* Push it! */
811 res = vm->nvram_push_config(vm,cfg_buffer,len);
812 free(cfg_buffer);
813 return(res);
814 }
815
816 /* Save general VM configuration into the specified file */
817 void vm_save_config(vm_instance_t *vm,FILE *fd)
818 {
819 if (vm->ios_image)
820 fprintf(fd,"vm set_ios %s %s\n",vm->name,vm->ios_image);
821
822 fprintf(fd,"vm set_ram %s %u\n",vm->name,vm->ram_size);
823 fprintf(fd,"vm set_nvram %s %u\n",vm->name,vm->nvram_size);
824 fprintf(fd,"vm set_ram_mmap %s %u\n",vm->name,vm->ram_mmap);
825 fprintf(fd,"vm set_clock_divisor %s %u\n",vm->name,vm->clock_divisor);
826 fprintf(fd,"vm set_conf_reg %s 0x%4.4x\n",vm->name,vm->conf_reg_setup);
827
828 if (vm->vtty_con_type == VTTY_TYPE_TCP)
829 fprintf(fd,"vm set_con_tcp_port %s %d\n",vm->name,vm->vtty_con_tcp_port);
830
831 if (vm->vtty_aux_type == VTTY_TYPE_TCP)
832 fprintf(fd,"vm set_aux_tcp_port %s %d\n",vm->name,vm->vtty_aux_tcp_port);
833 }

  ViewVC Help
Powered by ViewVC 1.1.26