]> git.proxmox.com Git - mirror_edk2.git/blame - UnixPkg/UnixBusDriverDxe/UnixBusDriver.c
Moving DuetPkg/CpuIoDxe to UefiCpuPkg.
[mirror_edk2.git] / UnixPkg / UnixBusDriverDxe / UnixBusDriver.c
CommitLineData
804405e7 1/*+++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
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
189 if (RemainingDevicePath->Type != HARDWARE_DEVICE_PATH ||\r
190 RemainingDevicePath->SubType != HW_VENDOR_DP ||\r
191 DevicePathNodeLength(RemainingDevicePath) != sizeof(UNIX_VENDOR_DEVICE_PATH_NODE)) {\r
192 return EFI_UNSUPPORTED;\r
193 }\r
194\r
195 for (Index = 0; Index < UNIX_PCD_ARRAY_SIZE; Index++) {\r
196 if (CompareGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid, mPcdEnvironment[Index].DevicePathGuid)) {\r
197 break;\r
198 }\r
199 }\r
200\r
201 if (Index >= UNIX_PCD_ARRAY_SIZE) {\r
202 return EFI_UNSUPPORTED;\r
203 }\r
204 }\r
205 \r
206 //\r
207 // Open the IO Abstraction(s) needed to perform the supported test\r
208 //\r
209 Status = gBS->OpenProtocol (\r
210 ControllerHandle,\r
211 &gEfiDevicePathProtocolGuid,\r
212 (VOID **)&ParentDevicePath,\r
213 This->DriverBindingHandle,\r
214 ControllerHandle,\r
215 EFI_OPEN_PROTOCOL_BY_DRIVER\r
216 );\r
217 if (Status == EFI_ALREADY_STARTED) {\r
218 return EFI_SUCCESS;\r
219 }\r
220\r
221 if (EFI_ERROR (Status)) {\r
222 return Status;\r
223 }\r
224\r
225 gBS->CloseProtocol (\r
226 ControllerHandle,\r
227 &gEfiDevicePathProtocolGuid,\r
228 This->DriverBindingHandle,\r
229 ControllerHandle\r
230 );\r
231\r
232 Status = gBS->OpenProtocol (\r
233 ControllerHandle,\r
234 &gEfiUnixThunkProtocolGuid,\r
235 (VOID **)&UnixThunk,\r
236 This->DriverBindingHandle,\r
237 ControllerHandle,\r
238 EFI_OPEN_PROTOCOL_BY_DRIVER\r
239 );\r
240 if (Status == EFI_ALREADY_STARTED) {\r
241 return EFI_SUCCESS;\r
242 }\r
243\r
244 if (EFI_ERROR (Status)) {\r
245 return Status;\r
246 }\r
247\r
248 //\r
249 // Since we call through UnixThunk we need to make sure it's valid\r
250 //\r
251 Status = EFI_SUCCESS;\r
252 if (UnixThunk->Signature != EFI_UNIX_THUNK_PROTOCOL_SIGNATURE) {\r
253 Status = EFI_UNSUPPORTED;\r
254 }\r
255\r
256 //\r
257 // Close the I/O Abstraction(s) used to perform the supported test\r
258 //\r
259 gBS->CloseProtocol (\r
260 ControllerHandle,\r
261 &gEfiUnixThunkProtocolGuid,\r
262 This->DriverBindingHandle,\r
263 ControllerHandle\r
264 );\r
265\r
266 return Status;\r
267}\r
268\r
269EFI_STATUS\r
270EFIAPI\r
271UnixBusDriverBindingStart (\r
272 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
273 IN EFI_HANDLE ControllerHandle,\r
274 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
275 )\r
276/*++\r
277\r
278Routine Description:\r
279\r
280Arguments:\r
281\r
282Returns:\r
283\r
284 None\r
285\r
286--*/\r
287// TODO: This - add argument and description to function comment\r
288// TODO: ControllerHandle - add argument and description to function comment\r
289// TODO: RemainingDevicePath - add argument and description to function comment\r
290// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
291// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
292// TODO: EFI_SUCCESS - add return value to function comment\r
293{\r
294 EFI_STATUS Status;\r
295 EFI_STATUS InstallStatus;\r
296 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;\r
297 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
298 UNIX_BUS_DEVICE *UnixBusDevice;\r
299 UNIX_IO_DEVICE *UnixDevice;\r
300 UINTN Index;\r
301 CHAR16 *StartString;\r
302 CHAR16 *SubString;\r
303 UINT16 Count;\r
304 UINTN StringSize;\r
305 UINT16 ComponentName[MAX_UNIX_ENVIRNMENT_VARIABLE_LENGTH];\r
306 UNIX_VENDOR_DEVICE_PATH_NODE *Node;\r
307 BOOLEAN CreateDevice;\r
308 CHAR16 *TempStr;\r
309 CHAR16 *PcdTempStr;\r
310 UINTN TempStrSize;\r
311\r
312 Status = EFI_UNSUPPORTED;\r
313\r
314 //\r
315 // Grab the protocols we need\r
316 //\r
317 Status = gBS->OpenProtocol (\r
318 ControllerHandle,\r
319 &gEfiDevicePathProtocolGuid,\r
320 (VOID **)&ParentDevicePath,\r
321 This->DriverBindingHandle,\r
322 ControllerHandle,\r
323 EFI_OPEN_PROTOCOL_BY_DRIVER\r
324 );\r
325 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
326 return Status;\r
327 }\r
328\r
329 Status = gBS->OpenProtocol (\r
330 ControllerHandle,\r
331 &gEfiUnixThunkProtocolGuid,\r
332 (VOID **)&UnixThunk,\r
333 This->DriverBindingHandle,\r
334 ControllerHandle,\r
335 EFI_OPEN_PROTOCOL_BY_DRIVER\r
336 );\r
337 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
338 return Status;\r
339 }\r
340\r
341 if (Status != EFI_ALREADY_STARTED) {\r
342 Status = gBS->AllocatePool (\r
343 EfiBootServicesData,\r
344 sizeof (UNIX_BUS_DEVICE),\r
345 (VOID *) &UnixBusDevice\r
346 );\r
347 if (EFI_ERROR (Status)) {\r
348 return Status;\r
349 }\r
350\r
351 UnixBusDevice->Signature = UNIX_BUS_DEVICE_SIGNATURE;\r
352 UnixBusDevice->ControllerNameTable = NULL;\r
353\r
354 AddUnicodeString (\r
355 "eng",\r
356 gUnixBusDriverComponentName.SupportedLanguages,\r
357 &UnixBusDevice->ControllerNameTable,\r
358 L"Unix Bus Controller"\r
359 );\r
360\r
361 Status = gBS->InstallMultipleProtocolInterfaces (\r
362 &ControllerHandle,\r
363 &gUnixBusDriverGuid,\r
364 UnixBusDevice,\r
365 NULL\r
366 );\r
367 if (EFI_ERROR (Status)) {\r
368 FreeUnicodeStringTable (UnixBusDevice->ControllerNameTable);\r
369 gBS->FreePool (UnixBusDevice);\r
370 return Status;\r
371 }\r
372 }\r
373\r
374 //\r
375 // Loop on the Variable list. Parse each variable to produce a set of handles that\r
376 // represent virtual hardware devices.\r
377 //\r
378 InstallStatus = EFI_NOT_FOUND;\r
379 for (Index = 0; Index < UNIX_PCD_ARRAY_SIZE; Index++) {\r
380 PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token);\r
381 ASSERT (PcdTempStr != NULL);\r
382\r
383 TempStrSize = StrLen (PcdTempStr);\r
384 TempStr = AllocateMemory ((TempStrSize * sizeof (CHAR16)) + 1);\r
385 StrCpy (TempStr, PcdTempStr);\r
386\r
387 StartString = TempStr;\r
388\r
389 //\r
390 // Parse the envirnment variable into sub strings using '!' as a delimator.\r
391 // Each substring needs it's own handle to be added to the system. This code\r
392 // does not understand the sub string. Thats the device drivers job.\r
393 //\r
394 Count = 0;\r
395 while (*StartString != '\0') {\r
396\r
397 //\r
398 // Find the end of the sub string\r
399 //\r
400 SubString = StartString;\r
401 while (*SubString != '\0' && *SubString != '!') {\r
402 SubString++;\r
403 }\r
404\r
405 if (*SubString == '!') {\r
406 //\r
407 // Replace token with '\0' to make sub strings. If this is the end\r
408 // of the string SubString will already point to NULL.\r
409 //\r
410 *SubString = '\0';\r
411 SubString++;\r
412 }\r
413\r
414 CreateDevice = TRUE;\r
415 if (RemainingDevicePath != NULL) {\r
416 CreateDevice = FALSE;\r
417 Node = (UNIX_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;\r
418 if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&\r
419 Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&\r
420 DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (UNIX_VENDOR_DEVICE_PATH_NODE)\r
421 ) {\r
422 if (CompareGuid (&Node->VendorDevicePath.Guid, mPcdEnvironment[Index].DevicePathGuid) &&\r
423 Node->Instance == Count\r
424 ) {\r
425 CreateDevice = TRUE;\r
426 }\r
427 }\r
428 }\r
429\r
430 if (CreateDevice) {\r
431 //\r
432 // Allocate instance structure, and fill in parent information.\r
433 //\r
434 UnixDevice = AllocateMemory (sizeof (UNIX_IO_DEVICE));\r
435 if (UnixDevice == NULL) {\r
436 return EFI_OUT_OF_RESOURCES;\r
437 }\r
438\r
439 UnixDevice->Handle = NULL;\r
440 UnixDevice->ControllerHandle = ControllerHandle;\r
441 UnixDevice->ParentDevicePath = ParentDevicePath;\r
442\r
443 UnixDevice->UnixIo.UnixThunk = UnixThunk;\r
444\r
445 //\r
446 // Plus 2 to account for the NULL at the end of the Unicode string\r
447 //\r
448 StringSize = (UINTN) ((UINT8 *) SubString - (UINT8 *) StartString) + sizeof (CHAR16);\r
449 UnixDevice->UnixIo.EnvString = AllocateMemory (StringSize);\r
450 if (UnixDevice->UnixIo.EnvString != NULL) {\r
451 CopyMem (UnixDevice->UnixIo.EnvString, StartString, StringSize);\r
452 }\r
453\r
454 UnixDevice->ControllerNameTable = NULL;\r
455\r
456 // FIXME: check size\r
457 StrCpy(ComponentName, UnixDevice->UnixIo.EnvString);\r
458\r
459 UnixDevice->DevicePath = UnixBusCreateDevicePath (\r
460 ParentDevicePath,\r
461 mPcdEnvironment[Index].DevicePathGuid,\r
462 Count\r
463 );\r
464 if (UnixDevice->DevicePath == NULL) {\r
465 gBS->FreePool (UnixDevice);\r
466 return EFI_OUT_OF_RESOURCES;\r
467 }\r
468\r
469 AddUnicodeString (\r
470 "eng",\r
471 gUnixBusDriverComponentName.SupportedLanguages,\r
472 &UnixDevice->ControllerNameTable,\r
473 ComponentName\r
474 );\r
475\r
476 UnixDevice->UnixIo.TypeGuid = mPcdEnvironment[Index].DevicePathGuid;\r
477 UnixDevice->UnixIo.InstanceNumber = Count;\r
478\r
479 UnixDevice->Signature = UNIX_IO_DEVICE_SIGNATURE;\r
480\r
481 Status = gBS->InstallMultipleProtocolInterfaces (\r
482 &UnixDevice->Handle,\r
483 &gEfiDevicePathProtocolGuid,\r
484 UnixDevice->DevicePath,\r
485 &gEfiUnixIoProtocolGuid,\r
486 &UnixDevice->UnixIo,\r
487 NULL\r
488 );\r
489 if (EFI_ERROR (Status)) {\r
490 FreeUnicodeStringTable (UnixDevice->ControllerNameTable);\r
491 gBS->FreePool (UnixDevice);\r
492 } else {\r
493 //\r
494 // Open For Child Device\r
495 //\r
496 Status = gBS->OpenProtocol (\r
497 ControllerHandle,\r
498 &gEfiUnixThunkProtocolGuid,\r
499 (VOID **)&UnixThunk,\r
500 This->DriverBindingHandle,\r
501 UnixDevice->Handle,\r
502 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
503 );\r
504 if (!EFI_ERROR (Status)) {\r
505 InstallStatus = EFI_SUCCESS;\r
506 }\r
507 }\r
508 }\r
509\r
510 //\r
511 // Parse Next sub string. This will point to '\0' if we are at the end.\r
512 //\r
513 Count++;\r
514 StartString = SubString;\r
515 }\r
516\r
517 gBS->FreePool (TempStr);\r
518 }\r
519\r
520 return EFI_SUCCESS;\r
521}\r
522\r
523\r
524EFI_STATUS\r
525EFIAPI\r
526UnixBusDriverBindingStop (\r
527 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
528 IN EFI_HANDLE ControllerHandle,\r
529 IN UINTN NumberOfChildren,\r
530 IN EFI_HANDLE *ChildHandleBuffer\r
531 )\r
532/*++\r
533\r
534Routine Description:\r
535\r
536Arguments:\r
537\r
538Returns:\r
539\r
540 None\r
541\r
542--*/\r
543// TODO: This - add argument and description to function comment\r
544// TODO: ControllerHandle - add argument and description to function comment\r
545// TODO: NumberOfChildren - add argument and description to function comment\r
546// TODO: ChildHandleBuffer - add argument and description to function comment\r
547// TODO: EFI_SUCCESS - add return value to function comment\r
548// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
549// TODO: EFI_SUCCESS - add return value to function comment\r
550{\r
551 EFI_STATUS Status;\r
552 UINTN Index;\r
553 BOOLEAN AllChildrenStopped;\r
554 EFI_UNIX_IO_PROTOCOL *UnixIo;\r
555 UNIX_BUS_DEVICE *UnixBusDevice;\r
556 UNIX_IO_DEVICE *UnixDevice;\r
557 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;\r
558\r
559 //\r
560 // Complete all outstanding transactions to Controller.\r
561 // Don't allow any new transaction to Controller to be started.\r
562 //\r
563\r
564 if (NumberOfChildren == 0) {\r
565 //\r
566 // Close the bus driver\r
567 //\r
568 Status = gBS->OpenProtocol (\r
569 ControllerHandle,\r
570 &gUnixBusDriverGuid,\r
571 (VOID **)&UnixBusDevice,\r
572 This->DriverBindingHandle,\r
573 ControllerHandle,\r
574 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
575 );\r
576 if (EFI_ERROR (Status)) {\r
577 return Status;\r
578 }\r
579\r
580 gBS->UninstallMultipleProtocolInterfaces (\r
581 ControllerHandle,\r
582 &gUnixBusDriverGuid,\r
583 UnixBusDevice,\r
584 NULL\r
585 );\r
586\r
587 FreeUnicodeStringTable (UnixBusDevice->ControllerNameTable);\r
588\r
589 gBS->FreePool (UnixBusDevice);\r
590\r
591 gBS->CloseProtocol (\r
592 ControllerHandle,\r
593 &gEfiUnixThunkProtocolGuid,\r
594 This->DriverBindingHandle,\r
595 ControllerHandle\r
596 );\r
597\r
598 gBS->CloseProtocol (\r
599 ControllerHandle,\r
600 &gEfiDevicePathProtocolGuid,\r
601 This->DriverBindingHandle,\r
602 ControllerHandle\r
603 );\r
604 return EFI_SUCCESS;\r
605 }\r
606\r
607 AllChildrenStopped = TRUE;\r
608\r
609 for (Index = 0; Index < NumberOfChildren; Index++) {\r
610\r
611 Status = gBS->OpenProtocol (\r
612 ChildHandleBuffer[Index],\r
613 &gEfiUnixIoProtocolGuid,\r
614 (VOID **)&UnixIo,\r
615 This->DriverBindingHandle,\r
616 ControllerHandle,\r
617 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
618 );\r
619 if (!EFI_ERROR (Status)) {\r
620\r
621 UnixDevice = UNIX_IO_DEVICE_FROM_THIS (UnixIo);\r
622\r
623 Status = gBS->CloseProtocol (\r
624 ControllerHandle,\r
625 &gEfiUnixThunkProtocolGuid,\r
626 This->DriverBindingHandle,\r
627 UnixDevice->Handle\r
628 );\r
629\r
630 Status = gBS->UninstallMultipleProtocolInterfaces (\r
631 UnixDevice->Handle,\r
632 &gEfiDevicePathProtocolGuid,\r
633 UnixDevice->DevicePath,\r
634 &gEfiUnixIoProtocolGuid,\r
635 &UnixDevice->UnixIo,\r
636 NULL\r
637 );\r
638\r
639 if (EFI_ERROR (Status)) {\r
640 gBS->OpenProtocol (\r
641 ControllerHandle,\r
642 &gEfiUnixThunkProtocolGuid,\r
643 (VOID **) &UnixThunk,\r
644 This->DriverBindingHandle,\r
645 UnixDevice->Handle,\r
646 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
647 );\r
648 } else {\r
649 //\r
650 // Close the child handle\r
651 //\r
652 FreeUnicodeStringTable (UnixDevice->ControllerNameTable);\r
653 gBS->FreePool (UnixDevice);\r
654 }\r
655 }\r
656\r
657 if (EFI_ERROR (Status)) {\r
658 AllChildrenStopped = FALSE;\r
659 }\r
660 }\r
661\r
662 if (!AllChildrenStopped) {\r
663 return EFI_DEVICE_ERROR;\r
664 }\r
665\r
666 return EFI_SUCCESS;\r
667}\r
668\r
669EFI_DEVICE_PATH_PROTOCOL *\r
670UnixBusCreateDevicePath (\r
671 IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath,\r
672 IN EFI_GUID *Guid,\r
673 IN UINT16 InstanceNumber\r
674 )\r
675/*++\r
676\r
677Routine Description:\r
678 Create a device path node using Guid and InstanceNumber and append it to\r
679 the passed in RootDevicePath\r
680\r
681Arguments:\r
682 RootDevicePath - Root of the device path to return.\r
683\r
684 Guid - GUID to use in vendor device path node.\r
685\r
686 InstanceNumber - Instance number to use in the vendor device path. This\r
687 argument is needed to make sure each device path is unique.\r
688\r
689Returns:\r
690\r
691 EFI_DEVICE_PATH_PROTOCOL \r
692\r
693--*/\r
694{\r
695 UNIX_VENDOR_DEVICE_PATH_NODE DevicePath;\r
696\r
697 DevicePath.VendorDevicePath.Header.Type = HARDWARE_DEVICE_PATH;\r
698 DevicePath.VendorDevicePath.Header.SubType = HW_VENDOR_DP;\r
699 SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (UNIX_VENDOR_DEVICE_PATH_NODE));\r
700\r
701 //\r
702 // The GUID defines the Class\r
703 //\r
704 CopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID));\r
705\r
706 //\r
707 // Add an instance number so we can make sure there are no Device Path\r
708 // duplication.\r
709 //\r
710 DevicePath.Instance = InstanceNumber;\r
711\r
712 return AppendDevicePathNode (\r
713 RootDevicePath,\r
714 (EFI_DEVICE_PATH_PROTOCOL *) &DevicePath\r
715 );\r
716}\r