]> git.proxmox.com Git - mirror_edk2.git/blame - UnixPkg/UnixBusDriverDxe/UnixBusDriver.c
Update the copyright notice format
[mirror_edk2.git] / UnixPkg / UnixBusDriverDxe / UnixBusDriver.c
CommitLineData
804405e7 1/*+++\r
2\r
f9b8ab56
HT
3Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials \r
804405e7 5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 UnixBusDriver.c\r
15\r
16Abstract:\r
17\r
18This following section documents the envirnoment variables for the Win UNIX \r
19build. These variables are used to define the (virtual) hardware \r
20configuration of the UNIX environment\r
21\r
22A ! can be used to seperate multiple instances in a variable. Each \r
23instance represents a seperate hardware device. \r
24\r
25EFI_UNIX_PHYSICAL_DISKS - maps to drives on your system\r
26EFI_UNIX_VIRTUAL_DISKS - maps to a device emulated by a file\r
27EFI_UNIX_FILE_SYSTEM - mouts a directory as a file system\r
28EFI_UNIX_CONSOLE - make a logical comand line window (only one!)\r
29EFI_UNIX_UGA - Builds UGA Windows of Width and Height\r
30\r
31 <F>ixed - Fixed disk like a hard drive.\r
32 <R>emovable - Removable media like a floppy or CD-ROM.\r
33 Read <O>nly - Write protected device.\r
34 Read <W>rite - Read write device.\r
35 <block count> - Decimal number of blocks a device supports.\r
36 <block size> - Decimal number of bytes per block.\r
37\r
38 UNIX envirnonment variable contents. '<' and '>' are not part of the variable, \r
39 they are just used to make this help more readable. There should be no \r
40 spaces between the ';'. Extra spaces will break the variable. A '!' is \r
41 used to seperate multiple devices in a variable.\r
42\r
43 EFI_UNIX_VIRTUAL_DISKS = \r
44 <F | R><O | W>;<block count>;<block size>[!...]\r
45\r
46 EFI_UNIX_PHYSICAL_DISKS =\r
47 <drive letter>:<F | R><O | W>;<block count>;<block size>[!...]\r
48\r
49 Virtual Disks: These devices use a file to emulate a hard disk or removable\r
50 media device. \r
51 \r
52 Thus a 20 MB emulated hard drive would look like:\r
53 EFI_UNIX_VIRTUAL_DISKS=FW;40960;512\r
54\r
55 A 1.44MB emulated floppy with a block size of 1024 would look like:\r
56 EFI_UNIX_VIRTUAL_DISKS=RW;1440;1024\r
57\r
58 Physical Disks: These devices use UNIX to open a real device in your system\r
59\r
60 Thus a 120 MB floppy would look like:\r
61 EFI_UNIX_PHYSICAL_DISKS=B:RW;245760;512\r
62\r
63 Thus a standard CD-ROM floppy would look like:\r
64 EFI_UNIX_PHYSICAL_DISKS=Z:RO;307200;2048\r
65\r
66 EFI_UNIX_FILE_SYSTEM = \r
67 <directory path>[!...]\r
68\r
69 Mounting the two directories C:\FOO and C:\BAR would look like:\r
70 EFI_UNIX_FILE_SYSTEM=c:\foo!c:\bar\r
71\r
72 EFI_UNIX_CONSOLE = \r
73 <window title>\r
74\r
75 Declaring a text console window with the title "My EFI Console" woild look like:\r
76 EFI_UNIX_CONSOLE=My EFI Console\r
77\r
78 EFI_UNIX_UGA = \r
79 <width> <height>[!...]\r
80\r
81 Declaring a two UGA windows with resolutions of 800x600 and 1024x768 would look like:\r
82 Example : EFI_UNIX_UGA=800 600!1024 768\r
83\r
84 EFI_UNIX_PASS_THROUGH =\r
85 <BaseAddress>;<Bus#>;<Device#>;<Function#>\r
86\r
87 Declaring a base address of 0xE0000000 (used for PCI Express devices)\r
88 and having NT32 talk to a device located at bus 0, device 1, function 0:\r
89 Example : EFI_UNIX_PASS_THROUGH=E000000;0;1;0\r
90\r
91---*/\r
92\r
93#include "UnixBusDriver.h"\r
94\r
95//\r
96// Define GUID for the Unix Bus Driver\r
97//\r
7492c63d 98EFI_GUID gUnixBusDriverGuid = {\r
804405e7 99 0x419f582, 0x625, 0x4531, {0x8a, 0x33, 0x85, 0xa9, 0x96, 0x5c, 0x95, 0xbc}\r
100};\r
101\r
102//\r
103// DriverBinding protocol global\r
104//\r
105EFI_DRIVER_BINDING_PROTOCOL gUnixBusDriverBinding = {\r
106 UnixBusDriverBindingSupported,\r
107 UnixBusDriverBindingStart,\r
108 UnixBusDriverBindingStop,\r
109 0xa,\r
110 NULL,\r
111 NULL\r
112};\r
113\r
114#define UNIX_PCD_ARRAY_SIZE (sizeof(mPcdEnvironment)/sizeof(UNIX_PCD_ENTRY))\r
115\r
116//\r
117// Table to map UNIX Environment variable to the GUID that should be in\r
118// device path.\r
119//\r
7492c63d 120UNIX_PCD_ENTRY mPcdEnvironment[] = {\r
804405e7 121 {PcdToken(PcdUnixConsole), &gEfiUnixConsoleGuid},\r
122 {PcdToken(PcdUnixUga), &gEfiUnixUgaGuid},\r
123 {PcdToken(PcdUnixFileSystem), &gEfiUnixFileSystemGuid},\r
124 {PcdToken(PcdUnixSerialPort), &gEfiUnixSerialPortGuid},\r
125 {PcdToken(PcdUnixVirtualDisk), &gEfiUnixVirtualDisksGuid},\r
126 {PcdToken(PcdUnixPhysicalDisk), &gEfiUnixPhysicalDisksGuid},\r
127 {PcdToken(PcdUnixCpuModel), &gEfiUnixCPUModelGuid},\r
128 {PcdToken(PcdUnixCpuSpeed), &gEfiUnixCPUSpeedGuid},\r
129 {PcdToken(PcdUnixMemorySize), &gEfiUnixMemoryGuid}\r
130};\r
131\r
132VOID *\r
133AllocateMemory (\r
134 IN UINTN Size\r
135 )\r
136{\r
137 EFI_STATUS Status;\r
138 VOID *Buffer;\r
139\r
140 Status = gBS->AllocatePool (\r
141 EfiBootServicesData,\r
142 Size,\r
143 (VOID *)&Buffer\r
144 );\r
145 if (EFI_ERROR (Status)) {\r
146 ASSERT (FALSE);\r
147 return NULL;\r
148 }\r
149 return Buffer;\r
150}\r
151\r
152\r
153EFI_STATUS\r
154EFIAPI\r
155UnixBusDriverBindingSupported (\r
156 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
157 IN EFI_HANDLE ControllerHandle,\r
158 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
159 )\r
160/*++\r
161\r
162Routine Description:\r
163\r
164Arguments:\r
165\r
166Returns:\r
167\r
168 None\r
169\r
170--*/\r
171// TODO: This - add argument and description to function comment\r
172// TODO: ControllerHandle - add argument and description to function comment\r
173// TODO: RemainingDevicePath - add argument and description to function comment\r
174// TODO: EFI_UNSUPPORTED - add return value to function comment\r
175// TODO: EFI_UNSUPPORTED - add return value to function comment\r
176// TODO: EFI_SUCCESS - add return value to function comment\r
177// TODO: EFI_SUCCESS - add return value to function comment\r
178{\r
179 EFI_STATUS Status;\r
180 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
181 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;\r
182 UINTN Index;\r
183\r
184 //\r
185 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure\r
186 // it is a legal Device Path Node for this bus driver's children.\r
187 //\r
188 if (RemainingDevicePath != NULL) {\r
af4a6385 189 //\r
190 // Check if RemainingDevicePath is the End of Device Path Node, \r
191 // if yes, go on checking other conditions\r
192 //\r
193 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
194 //\r
195 // If RemainingDevicePath isn't the End of Device Path Node,\r
196 // check its validation\r
197 //\r
198 if (RemainingDevicePath->Type != HARDWARE_DEVICE_PATH ||\r
199 RemainingDevicePath->SubType != HW_VENDOR_DP ||\r
200 DevicePathNodeLength(RemainingDevicePath) != sizeof(UNIX_VENDOR_DEVICE_PATH_NODE)) {\r
201 return EFI_UNSUPPORTED;\r
202 }\r
203 \r
204 for (Index = 0; Index < UNIX_PCD_ARRAY_SIZE; Index++) {\r
205 if (CompareGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid, mPcdEnvironment[Index].DevicePathGuid)) {\r
206 break;\r
207 }\r
208 }\r
209 \r
210 if (Index >= UNIX_PCD_ARRAY_SIZE) {\r
211 return EFI_UNSUPPORTED;\r
804405e7 212 }\r
804405e7 213 }\r
214 }\r
215 \r
216 //\r
217 // Open the IO Abstraction(s) needed to perform the supported test\r
218 //\r
219 Status = gBS->OpenProtocol (\r
220 ControllerHandle,\r
af4a6385 221 &gEfiUnixThunkProtocolGuid,\r
222 (VOID **)&UnixThunk,\r
804405e7 223 This->DriverBindingHandle,\r
224 ControllerHandle,\r
225 EFI_OPEN_PROTOCOL_BY_DRIVER\r
226 );\r
227 if (Status == EFI_ALREADY_STARTED) {\r
228 return EFI_SUCCESS;\r
229 }\r
230\r
231 if (EFI_ERROR (Status)) {\r
232 return Status;\r
233 }\r
234\r
af4a6385 235 //\r
236 // Close the I/O Abstraction(s) used to perform the supported test\r
237 //\r
804405e7 238 gBS->CloseProtocol (\r
239 ControllerHandle,\r
af4a6385 240 &gEfiUnixThunkProtocolGuid,\r
804405e7 241 This->DriverBindingHandle,\r
242 ControllerHandle\r
243 );\r
244\r
af4a6385 245 //\r
246 // Open the EFI Device Path protocol needed to perform the supported test\r
247 //\r
804405e7 248 Status = gBS->OpenProtocol (\r
249 ControllerHandle,\r
af4a6385 250 &gEfiDevicePathProtocolGuid,\r
251 (VOID **)&ParentDevicePath,\r
804405e7 252 This->DriverBindingHandle,\r
253 ControllerHandle,\r
254 EFI_OPEN_PROTOCOL_BY_DRIVER\r
255 );\r
256 if (Status == EFI_ALREADY_STARTED) {\r
257 return EFI_SUCCESS;\r
258 }\r
259\r
260 if (EFI_ERROR (Status)) {\r
261 return Status;\r
262 }\r
263\r
264 //\r
265 // Since we call through UnixThunk we need to make sure it's valid\r
266 //\r
267 Status = EFI_SUCCESS;\r
268 if (UnixThunk->Signature != EFI_UNIX_THUNK_PROTOCOL_SIGNATURE) {\r
269 Status = EFI_UNSUPPORTED;\r
270 }\r
271\r
7ee3b613 272 //\r
af4a6385 273 // Close protocol, don't use device path protocol in the Support() function\r
804405e7 274 //\r
275 gBS->CloseProtocol (\r
276 ControllerHandle,\r
af4a6385 277 &gEfiDevicePathProtocolGuid,\r
804405e7 278 This->DriverBindingHandle,\r
279 ControllerHandle\r
280 );\r
281\r
282 return Status;\r
283}\r
284\r
285EFI_STATUS\r
286EFIAPI\r
287UnixBusDriverBindingStart (\r
288 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
289 IN EFI_HANDLE ControllerHandle,\r
290 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
291 )\r
292/*++\r
293\r
294Routine Description:\r
295\r
296Arguments:\r
297\r
298Returns:\r
299\r
300 None\r
301\r
302--*/\r
303// TODO: This - add argument and description to function comment\r
304// TODO: ControllerHandle - add argument and description to function comment\r
305// TODO: RemainingDevicePath - add argument and description to function comment\r
306// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
307// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
308// TODO: EFI_SUCCESS - add return value to function comment\r
309{\r
310 EFI_STATUS Status;\r
311 EFI_STATUS InstallStatus;\r
312 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;\r
313 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
314 UNIX_BUS_DEVICE *UnixBusDevice;\r
315 UNIX_IO_DEVICE *UnixDevice;\r
316 UINTN Index;\r
317 CHAR16 *StartString;\r
318 CHAR16 *SubString;\r
319 UINT16 Count;\r
320 UINTN StringSize;\r
321 UINT16 ComponentName[MAX_UNIX_ENVIRNMENT_VARIABLE_LENGTH];\r
322 UNIX_VENDOR_DEVICE_PATH_NODE *Node;\r
323 BOOLEAN CreateDevice;\r
324 CHAR16 *TempStr;\r
325 CHAR16 *PcdTempStr;\r
326 UINTN TempStrSize;\r
327\r
328 Status = EFI_UNSUPPORTED;\r
329\r
330 //\r
331 // Grab the protocols we need\r
332 //\r
333 Status = gBS->OpenProtocol (\r
334 ControllerHandle,\r
335 &gEfiDevicePathProtocolGuid,\r
336 (VOID **)&ParentDevicePath,\r
337 This->DriverBindingHandle,\r
338 ControllerHandle,\r
339 EFI_OPEN_PROTOCOL_BY_DRIVER\r
340 );\r
341 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
342 return Status;\r
343 }\r
344\r
345 Status = gBS->OpenProtocol (\r
346 ControllerHandle,\r
347 &gEfiUnixThunkProtocolGuid,\r
348 (VOID **)&UnixThunk,\r
349 This->DriverBindingHandle,\r
350 ControllerHandle,\r
351 EFI_OPEN_PROTOCOL_BY_DRIVER\r
352 );\r
353 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
354 return Status;\r
355 }\r
356\r
357 if (Status != EFI_ALREADY_STARTED) {\r
358 Status = gBS->AllocatePool (\r
359 EfiBootServicesData,\r
360 sizeof (UNIX_BUS_DEVICE),\r
361 (VOID *) &UnixBusDevice\r
362 );\r
363 if (EFI_ERROR (Status)) {\r
364 return Status;\r
365 }\r
366\r
367 UnixBusDevice->Signature = UNIX_BUS_DEVICE_SIGNATURE;\r
368 UnixBusDevice->ControllerNameTable = NULL;\r
369\r
370 AddUnicodeString (\r
371 "eng",\r
372 gUnixBusDriverComponentName.SupportedLanguages,\r
373 &UnixBusDevice->ControllerNameTable,\r
374 L"Unix Bus Controller"\r
375 );\r
376\r
377 Status = gBS->InstallMultipleProtocolInterfaces (\r
378 &ControllerHandle,\r
379 &gUnixBusDriverGuid,\r
380 UnixBusDevice,\r
381 NULL\r
382 );\r
383 if (EFI_ERROR (Status)) {\r
384 FreeUnicodeStringTable (UnixBusDevice->ControllerNameTable);\r
385 gBS->FreePool (UnixBusDevice);\r
386 return Status;\r
387 }\r
388 }\r
389\r
390 //\r
391 // Loop on the Variable list. Parse each variable to produce a set of handles that\r
392 // represent virtual hardware devices.\r
393 //\r
394 InstallStatus = EFI_NOT_FOUND;\r
395 for (Index = 0; Index < UNIX_PCD_ARRAY_SIZE; Index++) {\r
396 PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token);\r
397 ASSERT (PcdTempStr != NULL);\r
398\r
399 TempStrSize = StrLen (PcdTempStr);\r
400 TempStr = AllocateMemory ((TempStrSize * sizeof (CHAR16)) + 1);\r
401 StrCpy (TempStr, PcdTempStr);\r
402\r
403 StartString = TempStr;\r
404\r
405 //\r
406 // Parse the envirnment variable into sub strings using '!' as a delimator.\r
407 // Each substring needs it's own handle to be added to the system. This code\r
408 // does not understand the sub string. Thats the device drivers job.\r
409 //\r
410 Count = 0;\r
411 while (*StartString != '\0') {\r
412\r
413 //\r
414 // Find the end of the sub string\r
415 //\r
416 SubString = StartString;\r
417 while (*SubString != '\0' && *SubString != '!') {\r
418 SubString++;\r
419 }\r
420\r
421 if (*SubString == '!') {\r
422 //\r
423 // Replace token with '\0' to make sub strings. If this is the end\r
424 // of the string SubString will already point to NULL.\r
425 //\r
426 *SubString = '\0';\r
427 SubString++;\r
428 }\r
429\r
430 CreateDevice = TRUE;\r
431 if (RemainingDevicePath != NULL) {\r
432 CreateDevice = FALSE;\r
af4a6385 433 //\r
434 // Check if RemainingDevicePath is the End of Device Path Node, \r
435 // if yes, don't create any child device \r
436 //\r
437 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
438 //\r
439 // If RemainingDevicePath isn't the End of Device Path Node,\r
440 // check its validation\r
441 //\r
442 Node = (UNIX_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;\r
443 if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&\r
444 Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&\r
445 DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (UNIX_VENDOR_DEVICE_PATH_NODE)\r
804405e7 446 ) {\r
af4a6385 447 if (CompareGuid (&Node->VendorDevicePath.Guid, mPcdEnvironment[Index].DevicePathGuid) &&\r
448 Node->Instance == Count\r
449 ) {\r
450 CreateDevice = TRUE;\r
451 }\r
804405e7 452 }\r
453 }\r
454 }\r
455\r
456 if (CreateDevice) {\r
457 //\r
458 // Allocate instance structure, and fill in parent information.\r
459 //\r
460 UnixDevice = AllocateMemory (sizeof (UNIX_IO_DEVICE));\r
461 if (UnixDevice == NULL) {\r
462 return EFI_OUT_OF_RESOURCES;\r
463 }\r
464\r
465 UnixDevice->Handle = NULL;\r
466 UnixDevice->ControllerHandle = ControllerHandle;\r
467 UnixDevice->ParentDevicePath = ParentDevicePath;\r
468\r
469 UnixDevice->UnixIo.UnixThunk = UnixThunk;\r
470\r
471 //\r
472 // Plus 2 to account for the NULL at the end of the Unicode string\r
473 //\r
474 StringSize = (UINTN) ((UINT8 *) SubString - (UINT8 *) StartString) + sizeof (CHAR16);\r
475 UnixDevice->UnixIo.EnvString = AllocateMemory (StringSize);\r
476 if (UnixDevice->UnixIo.EnvString != NULL) {\r
477 CopyMem (UnixDevice->UnixIo.EnvString, StartString, StringSize);\r
478 }\r
479\r
480 UnixDevice->ControllerNameTable = NULL;\r
481\r
482 // FIXME: check size\r
483 StrCpy(ComponentName, UnixDevice->UnixIo.EnvString);\r
484\r
485 UnixDevice->DevicePath = UnixBusCreateDevicePath (\r
486 ParentDevicePath,\r
487 mPcdEnvironment[Index].DevicePathGuid,\r
488 Count\r
489 );\r
490 if (UnixDevice->DevicePath == NULL) {\r
491 gBS->FreePool (UnixDevice);\r
492 return EFI_OUT_OF_RESOURCES;\r
493 }\r
494\r
495 AddUnicodeString (\r
496 "eng",\r
497 gUnixBusDriverComponentName.SupportedLanguages,\r
498 &UnixDevice->ControllerNameTable,\r
499 ComponentName\r
500 );\r
501\r
502 UnixDevice->UnixIo.TypeGuid = mPcdEnvironment[Index].DevicePathGuid;\r
503 UnixDevice->UnixIo.InstanceNumber = Count;\r
504\r
505 UnixDevice->Signature = UNIX_IO_DEVICE_SIGNATURE;\r
506\r
507 Status = gBS->InstallMultipleProtocolInterfaces (\r
508 &UnixDevice->Handle,\r
509 &gEfiDevicePathProtocolGuid,\r
510 UnixDevice->DevicePath,\r
511 &gEfiUnixIoProtocolGuid,\r
512 &UnixDevice->UnixIo,\r
513 NULL\r
514 );\r
515 if (EFI_ERROR (Status)) {\r
516 FreeUnicodeStringTable (UnixDevice->ControllerNameTable);\r
517 gBS->FreePool (UnixDevice);\r
518 } else {\r
519 //\r
520 // Open For Child Device\r
521 //\r
522 Status = gBS->OpenProtocol (\r
523 ControllerHandle,\r
524 &gEfiUnixThunkProtocolGuid,\r
525 (VOID **)&UnixThunk,\r
526 This->DriverBindingHandle,\r
527 UnixDevice->Handle,\r
528 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
529 );\r
530 if (!EFI_ERROR (Status)) {\r
531 InstallStatus = EFI_SUCCESS;\r
532 }\r
533 }\r
534 }\r
535\r
536 //\r
537 // Parse Next sub string. This will point to '\0' if we are at the end.\r
538 //\r
539 Count++;\r
540 StartString = SubString;\r
541 }\r
542\r
543 gBS->FreePool (TempStr);\r
544 }\r
545\r
546 return EFI_SUCCESS;\r
547}\r
548\r
549\r
550EFI_STATUS\r
551EFIAPI\r
552UnixBusDriverBindingStop (\r
553 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
554 IN EFI_HANDLE ControllerHandle,\r
555 IN UINTN NumberOfChildren,\r
556 IN EFI_HANDLE *ChildHandleBuffer\r
557 )\r
558/*++\r
559\r
560Routine Description:\r
561\r
562Arguments:\r
563\r
564Returns:\r
565\r
566 None\r
567\r
568--*/\r
569// TODO: This - add argument and description to function comment\r
570// TODO: ControllerHandle - add argument and description to function comment\r
571// TODO: NumberOfChildren - add argument and description to function comment\r
572// TODO: ChildHandleBuffer - add argument and description to function comment\r
573// TODO: EFI_SUCCESS - add return value to function comment\r
574// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
575// TODO: EFI_SUCCESS - add return value to function comment\r
576{\r
577 EFI_STATUS Status;\r
578 UINTN Index;\r
579 BOOLEAN AllChildrenStopped;\r
580 EFI_UNIX_IO_PROTOCOL *UnixIo;\r
581 UNIX_BUS_DEVICE *UnixBusDevice;\r
582 UNIX_IO_DEVICE *UnixDevice;\r
583 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;\r
584\r
585 //\r
586 // Complete all outstanding transactions to Controller.\r
587 // Don't allow any new transaction to Controller to be started.\r
588 //\r
589\r
590 if (NumberOfChildren == 0) {\r
591 //\r
592 // Close the bus driver\r
593 //\r
594 Status = gBS->OpenProtocol (\r
595 ControllerHandle,\r
596 &gUnixBusDriverGuid,\r
597 (VOID **)&UnixBusDevice,\r
598 This->DriverBindingHandle,\r
599 ControllerHandle,\r
600 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
601 );\r
602 if (EFI_ERROR (Status)) {\r
603 return Status;\r
604 }\r
605\r
606 gBS->UninstallMultipleProtocolInterfaces (\r
607 ControllerHandle,\r
608 &gUnixBusDriverGuid,\r
609 UnixBusDevice,\r
610 NULL\r
611 );\r
612\r
613 FreeUnicodeStringTable (UnixBusDevice->ControllerNameTable);\r
614\r
615 gBS->FreePool (UnixBusDevice);\r
616\r
617 gBS->CloseProtocol (\r
618 ControllerHandle,\r
619 &gEfiUnixThunkProtocolGuid,\r
620 This->DriverBindingHandle,\r
621 ControllerHandle\r
622 );\r
623\r
624 gBS->CloseProtocol (\r
625 ControllerHandle,\r
626 &gEfiDevicePathProtocolGuid,\r
627 This->DriverBindingHandle,\r
628 ControllerHandle\r
629 );\r
630 return EFI_SUCCESS;\r
631 }\r
632\r
633 AllChildrenStopped = TRUE;\r
634\r
635 for (Index = 0; Index < NumberOfChildren; Index++) {\r
636\r
637 Status = gBS->OpenProtocol (\r
638 ChildHandleBuffer[Index],\r
639 &gEfiUnixIoProtocolGuid,\r
640 (VOID **)&UnixIo,\r
641 This->DriverBindingHandle,\r
642 ControllerHandle,\r
643 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
644 );\r
645 if (!EFI_ERROR (Status)) {\r
646\r
647 UnixDevice = UNIX_IO_DEVICE_FROM_THIS (UnixIo);\r
648\r
649 Status = gBS->CloseProtocol (\r
650 ControllerHandle,\r
651 &gEfiUnixThunkProtocolGuid,\r
652 This->DriverBindingHandle,\r
653 UnixDevice->Handle\r
654 );\r
655\r
656 Status = gBS->UninstallMultipleProtocolInterfaces (\r
657 UnixDevice->Handle,\r
658 &gEfiDevicePathProtocolGuid,\r
659 UnixDevice->DevicePath,\r
660 &gEfiUnixIoProtocolGuid,\r
661 &UnixDevice->UnixIo,\r
662 NULL\r
663 );\r
664\r
665 if (EFI_ERROR (Status)) {\r
666 gBS->OpenProtocol (\r
667 ControllerHandle,\r
668 &gEfiUnixThunkProtocolGuid,\r
669 (VOID **) &UnixThunk,\r
670 This->DriverBindingHandle,\r
671 UnixDevice->Handle,\r
672 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
673 );\r
674 } else {\r
675 //\r
676 // Close the child handle\r
677 //\r
678 FreeUnicodeStringTable (UnixDevice->ControllerNameTable);\r
679 gBS->FreePool (UnixDevice);\r
680 }\r
681 }\r
682\r
683 if (EFI_ERROR (Status)) {\r
684 AllChildrenStopped = FALSE;\r
685 }\r
686 }\r
687\r
688 if (!AllChildrenStopped) {\r
689 return EFI_DEVICE_ERROR;\r
690 }\r
691\r
692 return EFI_SUCCESS;\r
693}\r
694\r
695EFI_DEVICE_PATH_PROTOCOL *\r
696UnixBusCreateDevicePath (\r
697 IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath,\r
698 IN EFI_GUID *Guid,\r
699 IN UINT16 InstanceNumber\r
700 )\r
701/*++\r
702\r
703Routine Description:\r
704 Create a device path node using Guid and InstanceNumber and append it to\r
705 the passed in RootDevicePath\r
706\r
707Arguments:\r
708 RootDevicePath - Root of the device path to return.\r
709\r
710 Guid - GUID to use in vendor device path node.\r
711\r
712 InstanceNumber - Instance number to use in the vendor device path. This\r
713 argument is needed to make sure each device path is unique.\r
714\r
715Returns:\r
716\r
717 EFI_DEVICE_PATH_PROTOCOL \r
718\r
719--*/\r
720{\r
721 UNIX_VENDOR_DEVICE_PATH_NODE DevicePath;\r
722\r
723 DevicePath.VendorDevicePath.Header.Type = HARDWARE_DEVICE_PATH;\r
724 DevicePath.VendorDevicePath.Header.SubType = HW_VENDOR_DP;\r
725 SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (UNIX_VENDOR_DEVICE_PATH_NODE));\r
726\r
727 //\r
728 // The GUID defines the Class\r
729 //\r
730 CopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID));\r
731\r
732 //\r
733 // Add an instance number so we can make sure there are no Device Path\r
734 // duplication.\r
735 //\r
736 DevicePath.Instance = InstanceNumber;\r
737\r
738 return AppendDevicePathNode (\r
739 RootDevicePath,\r
740 (EFI_DEVICE_PATH_PROTOCOL *) &DevicePath\r
741 );\r
742}\r