VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp@ 34406

Last change on this file since 34406 was 34010, checked in by vboxsync, 14 years ago

Main, FE/VBoxManage: Make it possible to mark specific controllers as bootable which means that the BIOS can access devices attached to the controller to boot from it

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 35.2 KB
Line 
1/* $Id: VBoxManageStorageController.cpp 34010 2010-11-11 20:17:47Z vboxsync $ */
2/** @file
3 * VBoxManage - The storage controller related commands.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef VBOX_ONLY_DOCS
19
20/*******************************************************************************
21* Header Files *
22*******************************************************************************/
23#include <VBox/com/com.h>
24#include <VBox/com/array.h>
25#include <VBox/com/ErrorInfo.h>
26#include <VBox/com/errorprint.h>
27#include <VBox/com/VirtualBox.h>
28
29#include <iprt/path.h>
30#include <iprt/param.h>
31#include <iprt/string.h>
32#include <iprt/ctype.h>
33#include <iprt/stream.h>
34#include <iprt/getopt.h>
35#include <VBox/log.h>
36
37#include "VBoxManage.h"
38using namespace com;
39
40
41// funcs
42///////////////////////////////////////////////////////////////////////////////
43
44
45static const RTGETOPTDEF g_aStorageAttachOptions[] =
46{
47 { "--storagectl", 's', RTGETOPT_REQ_STRING },
48 { "--port", 'p', RTGETOPT_REQ_UINT32 },
49 { "--device", 'd', RTGETOPT_REQ_UINT32 },
50 { "--medium", 'm', RTGETOPT_REQ_STRING },
51 { "--type", 't', RTGETOPT_REQ_STRING },
52 { "--passthrough", 'h', RTGETOPT_REQ_STRING },
53 { "--forceunmount", 'f', RTGETOPT_REQ_NOTHING },
54};
55
56int handleStorageAttach(HandlerArg *a)
57{
58 int c = VERR_INTERNAL_ERROR; /* initialized to shut up gcc */
59 HRESULT rc = S_OK;
60 ULONG port = ~0U;
61 ULONG device = ~0U;
62 bool fForceUnmount = false;
63 const char *pszCtl = NULL;
64 const char *pszType = NULL;
65 const char *pszMedium = NULL;
66 const char *pszPassThrough = NULL;
67 RTGETOPTUNION ValueUnion;
68 RTGETOPTSTATE GetState;
69 ComPtr<IMachine> machine;
70 ComPtr<IStorageController> storageCtl;
71 ComPtr<ISystemProperties> systemProperties;
72
73 if (a->argc < 9)
74 return errorSyntax(USAGE_STORAGEATTACH, "Too few parameters");
75 else if (a->argc > 13)
76 return errorSyntax(USAGE_STORAGEATTACH, "Too many parameters");
77
78 RTGetOptInit(&GetState, a->argc, a->argv, g_aStorageAttachOptions,
79 RT_ELEMENTS(g_aStorageAttachOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
80
81 while ( SUCCEEDED(rc)
82 && (c = RTGetOpt(&GetState, &ValueUnion)))
83 {
84 switch (c)
85 {
86 case 's': // storage controller name
87 {
88 if (ValueUnion.psz)
89 pszCtl = ValueUnion.psz;
90 else
91 rc = E_FAIL;
92 break;
93 }
94
95 case 'p': // port
96 {
97 port = ValueUnion.u32;
98 break;
99 }
100
101 case 'd': // device
102 {
103 device = ValueUnion.u32;
104 break;
105 }
106
107 case 'm': // medium <none|emptydrive|uuid|filename|host:<drive>>
108 {
109 if (ValueUnion.psz)
110 pszMedium = ValueUnion.psz;
111 else
112 rc = E_FAIL;
113 break;
114 }
115
116 case 't': // type <dvddrive|hdd|fdd>
117 {
118 if (ValueUnion.psz)
119 pszType = ValueUnion.psz;
120 else
121 rc = E_FAIL;
122 break;
123 }
124
125 case 'h': // passthrough <on|off>
126 {
127 if (ValueUnion.psz)
128 pszPassThrough = ValueUnion.psz;
129 else
130 rc = E_FAIL;
131 break;
132 }
133
134 case 'f': // force unmount medium during runtime
135 {
136 fForceUnmount = true;
137 break;
138 }
139
140 default:
141 {
142 errorGetOpt(USAGE_STORAGEATTACH, c, &ValueUnion);
143 rc = E_FAIL;
144 break;
145 }
146 }
147 }
148
149 if (FAILED(rc))
150 return 1;
151
152 if (!pszCtl)
153 return errorSyntax(USAGE_STORAGEATTACH, "Storage controller name not specified");
154 if (port == ~0U)
155 return errorSyntax(USAGE_STORAGEATTACH, "Port not specified");
156 if (device == ~0U)
157 return errorSyntax(USAGE_STORAGEATTACH, "Device not specified");
158
159 /* get the virtualbox system properties */
160 CHECK_ERROR_RET(a->virtualBox, COMGETTER(SystemProperties)(systemProperties.asOutParam()), 1);
161
162 /* try to find the given machine */
163 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
164 machine.asOutParam()), 1);
165
166 /* open a session for the VM (new or shared) */
167 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
168 SessionType_T st;
169 CHECK_ERROR_RET(a->session, COMGETTER(Type)(&st), 1);
170 bool fRunTime = (st == SessionType_Shared);
171
172 if (fRunTime && !RTStrICmp(pszType, "hdd"))
173 {
174 errorArgument("Hard disk drives cannot be changed while the VM is running\n");
175 goto leave;
176 }
177
178 if (fRunTime && !RTStrICmp(pszMedium, "none"))
179 {
180 errorArgument("Drives cannot be removed while the VM is running\n");
181 goto leave;
182 }
183
184 if (fRunTime && pszPassThrough)
185 {
186 errorArgument("Drive passthrough state can't be changed while the VM is running\n");
187 goto leave;
188 }
189
190 /* get the mutable session machine */
191 a->session->COMGETTER(Machine)(machine.asOutParam());
192
193 /* check if the storage controller is present */
194 rc = machine->GetStorageControllerByName(Bstr(pszCtl).raw(),
195 storageCtl.asOutParam());
196 if (FAILED(rc))
197 {
198 errorSyntax(USAGE_STORAGEATTACH, "Couldn't find the controller with the name: '%s'\n", pszCtl);
199 goto leave;
200 }
201
202 /* for sata controller check if the port count is big enough
203 * to accommodate the current port which is being assigned
204 * else just increase the port count
205 */
206 {
207 ULONG ulPortCount = 0;
208 ULONG ulMaxPortCount = 0;
209
210 CHECK_ERROR(storageCtl, COMGETTER(MaxPortCount)(&ulMaxPortCount));
211 CHECK_ERROR(storageCtl, COMGETTER(PortCount)(&ulPortCount));
212
213 if ( (ulPortCount != ulMaxPortCount)
214 && (port >= ulPortCount)
215 && (port < ulMaxPortCount))
216 CHECK_ERROR(storageCtl, COMSETTER(PortCount)(port + 1));
217 }
218
219 if (!RTStrICmp(pszMedium, "none"))
220 {
221 CHECK_ERROR(machine, DetachDevice(Bstr(pszCtl).raw(), port, device));
222 }
223 else if (!RTStrICmp(pszMedium, "emptydrive"))
224 {
225 if (fRunTime)
226 {
227 ComPtr<IMediumAttachment> mediumAttachment;
228 DeviceType_T deviceType = DeviceType_Null;
229 rc = machine->GetMediumAttachment(Bstr(pszCtl).raw(), port, device,
230 mediumAttachment.asOutParam());
231 if (SUCCEEDED(rc))
232 {
233 mediumAttachment->COMGETTER(Type)(&deviceType);
234
235 if ( (deviceType == DeviceType_DVD)
236 || (deviceType == DeviceType_Floppy))
237 {
238 /* just unmount the floppy/dvd */
239 CHECK_ERROR(machine, MountMedium(Bstr(pszCtl).raw(),
240 port,
241 device,
242 NULL,
243 fForceUnmount));
244 }
245 }
246
247 if ( FAILED(rc)
248 || !( deviceType == DeviceType_DVD
249 || deviceType == DeviceType_Floppy))
250 {
251 errorArgument("No DVD/Floppy Drive attached to the controller '%s'"
252 "at the port: %u, device: %u", pszCtl, port, device);
253 goto leave;
254 }
255
256 }
257 else
258 {
259 StorageBus_T storageBus = StorageBus_Null;
260 DeviceType_T deviceType = DeviceType_Null;
261 com::SafeArray <DeviceType_T> saDeviceTypes;
262 ULONG driveCheck = 0;
263
264 /* check if the device type is supported by the controller */
265 CHECK_ERROR(storageCtl, COMGETTER(Bus)(&storageBus));
266 CHECK_ERROR(systemProperties, GetDeviceTypesForStorageBus(storageBus, ComSafeArrayAsOutParam(saDeviceTypes)));
267 for (size_t i = 0; i < saDeviceTypes.size(); ++ i)
268 {
269 if ( (saDeviceTypes[i] == DeviceType_DVD)
270 || (saDeviceTypes[i] == DeviceType_Floppy))
271 driveCheck++;
272 }
273
274 if (!driveCheck)
275 {
276 errorArgument("The Attachment is not supported by the Storage Controller: '%s'", pszCtl);
277 goto leave;
278 }
279
280 if (storageBus == StorageBus_Floppy)
281 deviceType = DeviceType_Floppy;
282 else
283 deviceType = DeviceType_DVD;
284
285 /* attach a empty floppy/dvd drive after removing previous attachment */
286 machine->DetachDevice(Bstr(pszCtl).raw(), port, device);
287 CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl).raw(), port, device,
288 deviceType, NULL));
289 }
290 }
291 else
292 {
293 {
294 /*
295 * try to determine the type of the drive from the
296 * storage controller chipset, the attachment and
297 * the medium being attached
298 */
299 StorageControllerType_T ctlType = StorageControllerType_Null;
300 CHECK_ERROR(storageCtl, COMGETTER(ControllerType)(&ctlType));
301 if (ctlType == StorageControllerType_I82078)
302 {
303 /*
304 * floppy controller found so lets assume the medium
305 * given by the user is also a floppy image or floppy
306 * host drive
307 */
308 pszType = "fdd";
309 }
310 else
311 {
312 /*
313 * for SATA/SCSI/IDE it is hard to tell if it is a harddisk or
314 * a dvd being attached so lets check if the medium attachment
315 * and the medium, both are of same type. if yes then we are
316 * sure of its type and don't need the user to enter it manually
317 * else ask the user for the type.
318 */
319 ComPtr<IMediumAttachment> mediumAttachement;
320 rc = machine->GetMediumAttachment(Bstr(pszCtl).raw(), port,
321 device,
322 mediumAttachement.asOutParam());
323 if (SUCCEEDED(rc))
324 {
325 DeviceType_T deviceType;
326 mediumAttachement->COMGETTER(Type)(&deviceType);
327
328 if (deviceType == DeviceType_DVD)
329 {
330 ComPtr<IMedium> dvdMedium;
331 rc = a->virtualBox->FindMedium(Bstr(pszMedium).raw(),
332 DeviceType_DVD,
333 dvdMedium.asOutParam());
334 if (dvdMedium)
335 /*
336 * ok so the medium and attachment both are DVD's so it is
337 * safe to assume that we are dealing with a DVD here
338 */
339 pszType = "dvddrive";
340 }
341 else if (deviceType == DeviceType_HardDisk)
342 {
343 ComPtr<IMedium> hardDisk;
344 rc = a->virtualBox->FindMedium(Bstr(pszMedium).raw(),
345 DeviceType_HardDisk,
346 hardDisk.asOutParam());
347 if (hardDisk)
348 /*
349 * ok so the medium and attachment both are hdd's so it is
350 * safe to assume that we are dealing with a hdd here
351 */
352 pszType = "hdd";
353 }
354 }
355 }
356 /* for all other cases lets ask the user what type of drive it is */
357 }
358
359 if (!pszType)
360 {
361 errorSyntax(USAGE_STORAGEATTACH, "Argument --type not specified\n");
362 goto leave;
363 }
364
365 /* check if the device type is supported by the controller */
366 {
367 StorageBus_T storageBus = StorageBus_Null;
368 com::SafeArray <DeviceType_T> saDeviceTypes;
369
370 CHECK_ERROR(storageCtl, COMGETTER(Bus)(&storageBus));
371 CHECK_ERROR(systemProperties, GetDeviceTypesForStorageBus(storageBus, ComSafeArrayAsOutParam(saDeviceTypes)));
372 if (SUCCEEDED(rc))
373 {
374 ULONG driveCheck = 0;
375 for (size_t i = 0; i < saDeviceTypes.size(); ++ i)
376 {
377 if ( !RTStrICmp(pszType, "dvddrive")
378 && (saDeviceTypes[i] == DeviceType_DVD))
379 driveCheck++;
380
381 if ( !RTStrICmp(pszType, "hdd")
382 && (saDeviceTypes[i] == DeviceType_HardDisk))
383 driveCheck++;
384
385 if ( !RTStrICmp(pszType, "fdd")
386 && (saDeviceTypes[i] == DeviceType_Floppy))
387 driveCheck++;
388 }
389 if (!driveCheck)
390 {
391 errorArgument("The Attachment is not supported by the Storage Controller: '%s'", pszCtl);
392 goto leave;
393 }
394 }
395 else
396 goto leave;
397 }
398
399 if (!RTStrICmp(pszType, "dvddrive"))
400 {
401 ComPtr<IMedium> dvdMedium;
402
403 if (!fRunTime)
404 {
405 ComPtr<IMediumAttachment> mediumAttachement;
406
407 /* check if there is a dvd drive at the given location, if not attach one */
408 rc = machine->GetMediumAttachment(Bstr(pszCtl).raw(), port,
409 device,
410 mediumAttachement.asOutParam());
411 if (SUCCEEDED(rc))
412 {
413 DeviceType_T deviceType;
414 mediumAttachement->COMGETTER(Type)(&deviceType);
415
416 if (deviceType != DeviceType_DVD)
417 {
418 machine->DetachDevice(Bstr(pszCtl).raw(), port, device);
419 rc = machine->AttachDevice(Bstr(pszCtl).raw(), port,
420 device, DeviceType_DVD, NULL);
421 }
422 }
423 else
424 {
425 rc = machine->AttachDevice(Bstr(pszCtl).raw(), port,
426 device, DeviceType_DVD, NULL);
427 }
428 }
429
430 /* Attach/Detach the dvd medium now */
431 do
432 {
433 /* host drive? */
434 if (!RTStrNICmp(pszMedium, "host:", 5))
435 {
436 ComPtr<IHost> host;
437 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
438 rc = host->FindHostDVDDrive(Bstr(pszMedium + 5).raw(),
439 dvdMedium.asOutParam());
440 if (!dvdMedium)
441 {
442 /* 2nd try: try with the real name, important on Linux+libhal */
443 char szPathReal[RTPATH_MAX];
444 if (RT_FAILURE(RTPathReal(pszMedium + 5, szPathReal, sizeof(szPathReal))))
445 {
446 errorArgument("Invalid host DVD drive name \"%s\"", pszMedium + 5);
447 rc = E_FAIL;
448 break;
449 }
450 rc = host->FindHostDVDDrive(Bstr(szPathReal).raw(),
451 dvdMedium.asOutParam());
452 if (!dvdMedium)
453 {
454 errorArgument("Invalid host DVD drive name \"%s\"", pszMedium + 5);
455 rc = E_FAIL;
456 break;
457 }
458 }
459 }
460 else
461 {
462 rc = a->virtualBox->FindMedium(Bstr(pszMedium).raw(),
463 DeviceType_DVD,
464 dvdMedium.asOutParam());
465 if (FAILED(rc) || !dvdMedium)
466 {
467 /* not registered, do that on the fly */
468 Bstr emptyUUID;
469 CHECK_ERROR(a->virtualBox,
470 OpenMedium(Bstr(pszMedium).raw(),
471 DeviceType_DVD,
472 AccessMode_ReadWrite,
473 dvdMedium.asOutParam()));
474 }
475 if (!dvdMedium)
476 {
477 errorArgument("Invalid UUID or filename \"%s\"", pszMedium);
478 rc = E_FAIL;
479 break;
480 }
481 }
482 } while (0);
483
484 if (dvdMedium)
485 {
486 CHECK_ERROR(machine, MountMedium(Bstr(pszCtl).raw(), port,
487 device, dvdMedium,
488 fForceUnmount));
489 }
490 }
491 else if ( !RTStrICmp(pszType, "hdd")
492 && !fRunTime)
493 {
494 ComPtr<IMediumAttachment> mediumAttachement;
495
496 /* if there is anything attached at the given location, remove it */
497 machine->DetachDevice(Bstr(pszCtl).raw(), port, device);
498
499 /* first guess is that it's a UUID */
500 ComPtr<IMedium> hardDisk;
501 rc = a->virtualBox->FindMedium(Bstr(pszMedium).raw(),
502 DeviceType_HardDisk,
503 hardDisk.asOutParam());
504
505 /* not successful? Then it must be a filename */
506 if (!hardDisk)
507 {
508 /* open the new hard disk object */
509 CHECK_ERROR(a->virtualBox,
510 OpenMedium(Bstr(pszMedium).raw(),
511 DeviceType_HardDisk,
512 AccessMode_ReadWrite,
513 hardDisk.asOutParam()));
514 }
515
516 if (hardDisk)
517 {
518 CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl).raw(), port,
519 device, DeviceType_HardDisk,
520 hardDisk));
521 }
522 else
523 {
524 errorArgument("Invalid UUID or filename \"%s\"", pszMedium);
525 rc = E_FAIL;
526 }
527 }
528 else if (!RTStrICmp(pszType, "fdd"))
529 {
530 Bstr uuid;
531 ComPtr<IMedium> floppyMedium;
532 ComPtr<IMediumAttachment> floppyAttachment;
533 machine->GetMediumAttachment(Bstr(pszCtl).raw(), port, device,
534 floppyAttachment.asOutParam());
535
536 if ( !fRunTime
537 && !floppyAttachment)
538 CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl).raw(), port,
539 device, DeviceType_Floppy,
540 NULL));
541
542 /* host drive? */
543 if (!RTStrNICmp(pszMedium, "host:", 5))
544 {
545 ComPtr<IHost> host;
546
547 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
548 rc = host->FindHostFloppyDrive(Bstr(pszMedium + 5).raw(),
549 floppyMedium.asOutParam());
550 if (!floppyMedium)
551 {
552 errorArgument("Invalid host floppy drive name \"%s\"", pszMedium + 5);
553 rc = E_FAIL;
554 }
555 }
556 else
557 {
558 /* first assume it's a UUID */
559 rc = a->virtualBox->FindMedium(Bstr(pszMedium).raw(),
560 DeviceType_Floppy,
561 floppyMedium.asOutParam());
562 if (FAILED(rc) || !floppyMedium)
563 {
564 /* not registered, do that on the fly */
565 Bstr emptyUUID;
566 CHECK_ERROR(a->virtualBox,
567 OpenMedium(Bstr(pszMedium).raw(),
568 DeviceType_Floppy,
569 AccessMode_ReadWrite,
570 floppyMedium.asOutParam()));
571 }
572
573 if (!floppyMedium)
574 {
575 errorArgument("Invalid UUID or filename \"%s\"", pszMedium);
576 rc = E_FAIL;
577 }
578 }
579
580 if (floppyMedium)
581 {
582 CHECK_ERROR(machine, MountMedium(Bstr(pszCtl).raw(), port,
583 device,
584 floppyMedium,
585 fForceUnmount));
586 }
587 }
588 else
589 {
590 errorArgument("Invalid --type argument '%s'", pszType);
591 rc = E_FAIL;
592 }
593 }
594
595 if ( pszPassThrough
596 && (SUCCEEDED(rc)))
597 {
598 ComPtr<IMediumAttachment> mattach;
599
600 CHECK_ERROR(machine, GetMediumAttachment(Bstr(pszCtl).raw(), port,
601 device, mattach.asOutParam()));
602
603 if (SUCCEEDED(rc))
604 {
605 if (!RTStrICmp(pszPassThrough, "on"))
606 {
607 CHECK_ERROR(machine, PassthroughDevice(Bstr(pszCtl).raw(),
608 port, device, TRUE));
609 }
610 else if (!RTStrICmp(pszPassThrough, "off"))
611 {
612 CHECK_ERROR(machine, PassthroughDevice(Bstr(pszCtl).raw(),
613 port, device, FALSE));
614 }
615 else
616 {
617 errorArgument("Invalid --passthrough argument '%s'", pszPassThrough);
618 rc = E_FAIL;
619 }
620 }
621 else
622 {
623 errorArgument("Couldn't find the controller attachment for the controller '%s'\n", pszCtl);
624 rc = E_FAIL;
625 }
626 }
627
628 /* commit changes */
629 if (SUCCEEDED(rc))
630 CHECK_ERROR(machine, SaveSettings());
631
632leave:
633 /* it's important to always close sessions */
634 a->session->UnlockMachine();
635
636 return SUCCEEDED(rc) ? 0 : 1;
637}
638
639
640static const RTGETOPTDEF g_aStorageControllerOptions[] =
641{
642 { "--name", 'n', RTGETOPT_REQ_STRING },
643 { "--add", 'a', RTGETOPT_REQ_STRING },
644 { "--controller", 'c', RTGETOPT_REQ_STRING },
645 { "--sataideemulation", 'e', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_INDEX },
646 { "--sataportcount", 'p', RTGETOPT_REQ_UINT32 },
647 { "--remove", 'r', RTGETOPT_REQ_NOTHING },
648 { "--hostiocache", 'i', RTGETOPT_REQ_STRING },
649 { "--bootable", 'b', RTGETOPT_REQ_STRING },
650};
651
652int handleStorageController(HandlerArg *a)
653{
654 int c;
655 HRESULT rc = S_OK;
656 const char *pszCtl = NULL;
657 const char *pszBusType = NULL;
658 const char *pszCtlType = NULL;
659 const char *pszHostIOCache = NULL;
660 const char *pszBootable = NULL;
661 ULONG satabootdev = ~0U;
662 ULONG sataidedev = ~0U;
663 ULONG sataportcount = ~0U;
664 bool fRemoveCtl = false;
665 ComPtr<IMachine> machine;
666 RTGETOPTUNION ValueUnion;
667 RTGETOPTSTATE GetState;
668
669 if (a->argc < 4)
670 return errorSyntax(USAGE_STORAGECONTROLLER, "Too few parameters");
671
672 RTGetOptInit (&GetState, a->argc, a->argv, g_aStorageControllerOptions,
673 RT_ELEMENTS(g_aStorageControllerOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
674
675 while ( SUCCEEDED(rc)
676 && (c = RTGetOpt(&GetState, &ValueUnion)))
677 {
678 switch (c)
679 {
680 case 'n': // controller name
681 {
682 if (ValueUnion.psz)
683 pszCtl = ValueUnion.psz;
684 else
685 rc = E_FAIL;
686 break;
687 }
688
689 case 'a': // controller bus type <ide/sata/scsi/floppy>
690 {
691 if (ValueUnion.psz)
692 pszBusType = ValueUnion.psz;
693 else
694 rc = E_FAIL;
695 break;
696 }
697
698 case 'c': // controller <lsilogic/buslogic/intelahci/piix3/piix4/ich6/i82078>
699 {
700 if (ValueUnion.psz)
701 pszCtlType = ValueUnion.psz;
702 else
703 rc = E_FAIL;
704 break;
705 }
706
707 case 'e': // sataideemulation
708 {
709 satabootdev = GetState.uIndex;
710 sataidedev = ValueUnion.u32;
711 break;
712 }
713
714 case 'p': // sataportcount
715 {
716 sataportcount = ValueUnion.u32;
717 break;
718 }
719
720 case 'r': // remove controller
721 {
722 fRemoveCtl = true;
723 break;
724 }
725
726 case 'i':
727 {
728 pszHostIOCache = ValueUnion.psz;
729 break;
730 }
731
732 case 'b':
733 {
734 pszBootable = ValueUnion.psz;
735 break;
736 }
737
738 default:
739 {
740 errorGetOpt(USAGE_STORAGECONTROLLER, c, &ValueUnion);
741 rc = E_FAIL;
742 break;
743 }
744 }
745 }
746
747 if (FAILED(rc))
748 return 1;
749
750 /* try to find the given machine */
751 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
752 machine.asOutParam()), 1);
753
754 /* open a session for the VM */
755 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1);
756
757 /* get the mutable session machine */
758 a->session->COMGETTER(Machine)(machine.asOutParam());
759
760 if (!pszCtl)
761 {
762 /* it's important to always close sessions */
763 a->session->UnlockMachine();
764 errorSyntax(USAGE_STORAGECONTROLLER, "Storage controller name not specified\n");
765 return 1;
766 }
767
768 if (fRemoveCtl)
769 {
770 com::SafeIfaceArray<IMediumAttachment> mediumAttachments;
771
772 CHECK_ERROR(machine,
773 GetMediumAttachmentsOfController(Bstr(pszCtl).raw(),
774 ComSafeArrayAsOutParam(mediumAttachments)));
775 for (size_t i = 0; i < mediumAttachments.size(); ++ i)
776 {
777 ComPtr<IMediumAttachment> mediumAttach = mediumAttachments[i];
778 LONG port = 0;
779 LONG device = 0;
780
781 CHECK_ERROR(mediumAttach, COMGETTER(Port)(&port));
782 CHECK_ERROR(mediumAttach, COMGETTER(Device)(&device));
783 CHECK_ERROR(machine, DetachDevice(Bstr(pszCtl).raw(), port, device));
784 }
785
786 if (SUCCEEDED(rc))
787 CHECK_ERROR(machine, RemoveStorageController(Bstr(pszCtl).raw()));
788 else
789 errorArgument("Can't detach the devices connected to '%s' Controller\n"
790 "and thus its removal failed.", pszCtl);
791 }
792 else
793 {
794 if (pszBusType)
795 {
796 ComPtr<IStorageController> ctl;
797
798 if (!RTStrICmp(pszBusType, "ide"))
799 {
800 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(),
801 StorageBus_IDE,
802 ctl.asOutParam()));
803 }
804 else if (!RTStrICmp(pszBusType, "sata"))
805 {
806 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(),
807 StorageBus_SATA,
808 ctl.asOutParam()));
809 }
810 else if (!RTStrICmp(pszBusType, "scsi"))
811 {
812 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(),
813 StorageBus_SCSI,
814 ctl.asOutParam()));
815 }
816 else if (!RTStrICmp(pszBusType, "floppy"))
817 {
818 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(),
819 StorageBus_Floppy,
820 ctl.asOutParam()));
821 }
822 else if (!RTStrICmp(pszBusType, "sas"))
823 {
824 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(),
825 StorageBus_SAS,
826 ctl.asOutParam()));
827 }
828 else
829 {
830 errorArgument("Invalid --add argument '%s'", pszBusType);
831 rc = E_FAIL;
832 }
833 }
834
835 if ( pszCtlType
836 && SUCCEEDED(rc))
837 {
838 ComPtr<IStorageController> ctl;
839
840 CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl).raw(),
841 ctl.asOutParam()));
842
843 if (SUCCEEDED(rc))
844 {
845 if (!RTStrICmp(pszCtlType, "lsilogic"))
846 {
847 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_LsiLogic));
848 }
849 else if (!RTStrICmp(pszCtlType, "buslogic"))
850 {
851 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_BusLogic));
852 }
853 else if (!RTStrICmp(pszCtlType, "intelahci"))
854 {
855 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_IntelAhci));
856 }
857 else if (!RTStrICmp(pszCtlType, "piix3"))
858 {
859 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_PIIX3));
860 }
861 else if (!RTStrICmp(pszCtlType, "piix4"))
862 {
863 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_PIIX4));
864 }
865 else if (!RTStrICmp(pszCtlType, "ich6"))
866 {
867 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_ICH6));
868 }
869 else if (!RTStrICmp(pszCtlType, "i82078"))
870 {
871 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_I82078));
872 }
873 else if (!RTStrICmp(pszCtlType, "lsilogicsas"))
874 {
875 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_LsiLogicSas));
876 }
877 else
878 {
879 errorArgument("Invalid --type argument '%s'", pszCtlType);
880 rc = E_FAIL;
881 }
882 }
883 else
884 {
885 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
886 rc = E_FAIL;
887 }
888 }
889
890 if ( (sataportcount != ~0U)
891 && SUCCEEDED(rc))
892 {
893 ComPtr<IStorageController> ctl;
894
895 CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl).raw(),
896 ctl.asOutParam()));
897
898 if (SUCCEEDED(rc))
899 {
900 CHECK_ERROR(ctl, COMSETTER(PortCount)(sataportcount));
901 }
902 else
903 {
904 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
905 rc = E_FAIL;
906 }
907 }
908
909 if ( (sataidedev != ~0U)
910 && (satabootdev != ~0U)
911 && SUCCEEDED(rc))
912 {
913 ComPtr<IStorageController> ctl;
914
915 CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl).raw(),
916 ctl.asOutParam()));
917
918 if (SUCCEEDED(rc))
919 {
920 CHECK_ERROR(ctl, SetIDEEmulationPort(satabootdev, sataidedev));
921 }
922 else
923 {
924 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
925 rc = E_FAIL;
926 }
927 }
928
929 if ( pszHostIOCache
930 && SUCCEEDED(rc))
931 {
932 ComPtr<IStorageController> ctl;
933
934 CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl).raw(),
935 ctl.asOutParam()));
936
937 if (SUCCEEDED(rc))
938 {
939 if (!RTStrICmp(pszHostIOCache, "on"))
940 {
941 CHECK_ERROR(ctl, COMSETTER(UseHostIOCache)(TRUE));
942 }
943 else if (!RTStrICmp(pszHostIOCache, "off"))
944 {
945 CHECK_ERROR(ctl, COMSETTER(UseHostIOCache)(FALSE));
946 }
947 else
948 {
949 errorArgument("Invalid --hostiocache argument '%s'", pszHostIOCache);
950 rc = E_FAIL;
951 }
952 }
953 else
954 {
955 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
956 rc = E_FAIL;
957 }
958 }
959
960 if ( pszBootable
961 && SUCCEEDED(rc))
962 {
963 if (SUCCEEDED(rc))
964 {
965 if (!RTStrICmp(pszBootable, "on"))
966 {
967 CHECK_ERROR(machine, SetStorageControllerBootable(Bstr(pszCtl).raw(), TRUE));
968 }
969 else if (!RTStrICmp(pszBootable, "off"))
970 {
971 CHECK_ERROR(machine, SetStorageControllerBootable(Bstr(pszCtl).raw(), FALSE));
972 }
973 else
974 {
975 errorArgument("Invalid --bootable argument '%s'", pszHostIOCache);
976 rc = E_FAIL;
977 }
978 }
979 else
980 {
981 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
982 rc = E_FAIL;
983 }
984 }
985 }
986
987 /* commit changes */
988 if (SUCCEEDED(rc))
989 CHECK_ERROR(machine, SaveSettings());
990
991 /* it's important to always close sessions */
992 a->session->UnlockMachine();
993
994 return SUCCEEDED(rc) ? 0 : 1;
995}
996
997#endif /* !VBOX_ONLY_DOCS */
998
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette