]> git.proxmox.com Git - mirror_edk2.git/blame - EdkUnixPkg/Dxe/UnixThunk/Bus/UnixBusDriver/UnixBusDriver.c
Unix version of EFI emulator
[mirror_edk2.git] / EdkUnixPkg / Dxe / UnixThunk / Bus / UnixBusDriver / UnixBusDriver.c
CommitLineData
c9093a06 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 NT \r
19build. These variables are used to define the (virtual) hardware \r
20configuration of the NT 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 NT 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 NT 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//#include "PciHostBridge.h"\r
95\r
96//\r
97// Define GUID for the Unix Bus Driver\r
98//\r
99static EFI_GUID gUnixBusDriverGuid = {\r
100 0x419f582, 0x625, 0x4531, 0x8a, 0x33, 0x85, 0xa9, 0x96, 0x5c, 0x95, 0xbc\r
101};\r
102\r
103//\r
104// DriverBinding protocol global\r
105//\r
106EFI_DRIVER_BINDING_PROTOCOL gUnixBusDriverBinding = {\r
107 UnixBusDriverBindingSupported,\r
108 UnixBusDriverBindingStart,\r
109 UnixBusDriverBindingStop,\r
110 0x10,\r
111 NULL,\r
112 NULL\r
113};\r
114\r
115#define UNIX_PCD_ARRAY_SIZE (sizeof(mPcdEnvironment)/sizeof(UNIX_PCD_ENTRY))\r
116\r
117//\r
118// Table to map NT Environment variable to the GUID that should be in\r
119// device path.\r
120//\r
121static UNIX_PCD_ENTRY mPcdEnvironment[] = {\r
122 {PcdToken(PcdUnixConsole), &gEfiUnixConsoleGuid},\r
123 {PcdToken(PcdUnixUga), &gEfiUnixUgaGuid},\r
124 {PcdToken(PcdUnixFileSystem), &gEfiUnixFileSystemGuid},\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 //\r
433 // Allocate instance structure, and fill in parent information.\r
434 //\r
435 UnixDevice = AllocateMemory (sizeof (UNIX_IO_DEVICE));\r
436 if (UnixDevice == NULL) {\r
437 return EFI_OUT_OF_RESOURCES;\r
438 }\r
439\r
440 UnixDevice->Handle = NULL;\r
441 UnixDevice->ControllerHandle = ControllerHandle;\r
442 UnixDevice->ParentDevicePath = ParentDevicePath;\r
443\r
444 UnixDevice->UnixIo.UnixThunk = UnixThunk;\r
445\r
446 //\r
447 // Plus 2 to account for the NULL at the end of the Unicode string\r
448 //\r
449 StringSize = (UINTN) ((UINT8 *) SubString - (UINT8 *) StartString) + sizeof (CHAR16);\r
450 UnixDevice->UnixIo.EnvString = AllocateMemory (StringSize);\r
451 if (UnixDevice->UnixIo.EnvString != NULL) {\r
452 CopyMem (UnixDevice->UnixIo.EnvString, StartString, StringSize);\r
453 }\r
454\r
455 UnixDevice->ControllerNameTable = NULL;\r
456\r
457 // FIXME: check size
458 StrCpy(ComponentName, UnixDevice->UnixIo.EnvString);\r
459\r
460 UnixDevice->DevicePath = UnixBusCreateDevicePath (\r
461 ParentDevicePath,\r
462 mPcdEnvironment[Index].DevicePathGuid,\r
463 Count\r
464 );\r
465 if (UnixDevice->DevicePath == NULL) {\r
466 gBS->FreePool (UnixDevice);\r
467 return EFI_OUT_OF_RESOURCES;\r
468 }\r
469\r
470 AddUnicodeString (\r
471 "eng",\r
472 gUnixBusDriverComponentName.SupportedLanguages,\r
473 &UnixDevice->ControllerNameTable,\r
474 ComponentName\r
475 );\r
476\r
477 UnixDevice->UnixIo.TypeGuid = mPcdEnvironment[Index].DevicePathGuid;\r
478 UnixDevice->UnixIo.InstanceNumber = Count;\r
479\r
480 UnixDevice->Signature = UNIX_IO_DEVICE_SIGNATURE;\r
481\r
482 Status = gBS->InstallMultipleProtocolInterfaces (\r
483 &UnixDevice->Handle,\r
484 &gEfiDevicePathProtocolGuid,\r
485 UnixDevice->DevicePath,\r
486 &gEfiUnixIoProtocolGuid,\r
487 &UnixDevice->UnixIo,\r
488 NULL\r
489 );\r
490 if (EFI_ERROR (Status)) {\r
491 FreeUnicodeStringTable (UnixDevice->ControllerNameTable);\r
492 gBS->FreePool (UnixDevice);\r
493 } else {\r
494 //\r
495 // Open For Child Device\r
496 //\r
497 Status = gBS->OpenProtocol (\r
498 ControllerHandle,\r
499 &gEfiUnixThunkProtocolGuid,\r
500 (VOID **)&UnixThunk,\r
501 This->DriverBindingHandle,\r
502 UnixDevice->Handle,\r
503 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
504 );\r
505 if (!EFI_ERROR (Status)) {\r
506 InstallStatus = EFI_SUCCESS;\r
507 }\r
508 }\r
509 }\r
510\r
511 //\r
512 // Parse Next sub string. This will point to '\0' if we are at the end.\r
513 //\r
514 Count++;\r
515 StartString = SubString;\r
516 }\r
517\r
518 gBS->FreePool (TempStr);\r
519 }\r
520\r
521 return EFI_SUCCESS;\r
522}\r
523\r
524\r
525EFI_STATUS\r
526EFIAPI\r
527UnixBusDriverBindingStop (\r
528 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
529 IN EFI_HANDLE ControllerHandle,\r
530 IN UINTN NumberOfChildren,\r
531 IN EFI_HANDLE *ChildHandleBuffer\r
532 )\r
533/*++\r
534\r
535Routine Description:\r
536\r
537Arguments:\r
538\r
539Returns:\r
540\r
541 None\r
542\r
543--*/\r
544// TODO: This - add argument and description to function comment\r
545// TODO: ControllerHandle - add argument and description to function comment\r
546// TODO: NumberOfChildren - add argument and description to function comment\r
547// TODO: ChildHandleBuffer - add argument and description to function comment\r
548// TODO: EFI_SUCCESS - add return value to function comment\r
549// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
550// TODO: EFI_SUCCESS - add return value to function comment\r
551{\r
552 EFI_STATUS Status;\r
553 UINTN Index;\r
554 BOOLEAN AllChildrenStopped;\r
555 EFI_UNIX_IO_PROTOCOL *UnixIo;\r
556 UNIX_BUS_DEVICE *UnixBusDevice;\r
557 UNIX_IO_DEVICE *UnixDevice;\r
558 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;\r
559\r
560 //\r
561 // Complete all outstanding transactions to Controller.\r
562 // Don't allow any new transaction to Controller to be started.\r
563 //\r
564\r
565 if (NumberOfChildren == 0) {\r
566 //\r
567 // Close the bus driver\r
568 //\r
569 Status = gBS->OpenProtocol (\r
570 ControllerHandle,\r
571 &gUnixBusDriverGuid,\r
572 (VOID **)&UnixBusDevice,\r
573 This->DriverBindingHandle,\r
574 ControllerHandle,\r
575 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
576 );\r
577 if (EFI_ERROR (Status)) {\r
578 return Status;\r
579 }\r
580\r
581 gBS->UninstallMultipleProtocolInterfaces (\r
582 ControllerHandle,\r
583 &gUnixBusDriverGuid,\r
584 UnixBusDevice,\r
585 NULL\r
586 );\r
587\r
588 FreeUnicodeStringTable (UnixBusDevice->ControllerNameTable);\r
589\r
590 gBS->FreePool (UnixBusDevice);\r
591\r
592 gBS->CloseProtocol (\r
593 ControllerHandle,\r
594 &gEfiUnixThunkProtocolGuid,\r
595 This->DriverBindingHandle,\r
596 ControllerHandle\r
597 );\r
598\r
599 gBS->CloseProtocol (\r
600 ControllerHandle,\r
601 &gEfiDevicePathProtocolGuid,\r
602 This->DriverBindingHandle,\r
603 ControllerHandle\r
604 );\r
605 return EFI_SUCCESS;\r
606 }\r
607\r
608 AllChildrenStopped = TRUE;\r
609\r
610 for (Index = 0; Index < NumberOfChildren; Index++) {\r
611\r
612 Status = gBS->OpenProtocol (\r
613 ChildHandleBuffer[Index],\r
614 &gEfiUnixIoProtocolGuid,\r
615 (VOID **)&UnixIo,\r
616 This->DriverBindingHandle,\r
617 ControllerHandle,\r
618 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
619 );\r
620 if (!EFI_ERROR (Status)) {\r
621\r
622 UnixDevice = UNIX_IO_DEVICE_FROM_THIS (UnixIo);\r
623\r
624 Status = gBS->CloseProtocol (\r
625 ControllerHandle,\r
626 &gEfiUnixThunkProtocolGuid,\r
627 This->DriverBindingHandle,\r
628 UnixDevice->Handle\r
629 );\r
630\r
631 Status = gBS->UninstallMultipleProtocolInterfaces (\r
632 UnixDevice->Handle,\r
633 &gEfiDevicePathProtocolGuid,\r
634 UnixDevice->DevicePath,\r
635 &gEfiUnixIoProtocolGuid,\r
636 &UnixDevice->UnixIo,\r
637 NULL\r
638 );\r
639\r
640 if (EFI_ERROR (Status)) {\r
641 gBS->OpenProtocol (\r
642 ControllerHandle,\r
643 &gEfiUnixThunkProtocolGuid,\r
644 (VOID **) &UnixThunk,\r
645 This->DriverBindingHandle,\r
646 UnixDevice->Handle,\r
647 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
648 );\r
649 } else {\r
650 //\r
651 // Close the child handle\r
652 //\r
653 FreeUnicodeStringTable (UnixDevice->ControllerNameTable);\r
654 gBS->FreePool (UnixDevice);\r
655 }\r
656 }\r
657\r
658 if (EFI_ERROR (Status)) {\r
659 AllChildrenStopped = FALSE;\r
660 }\r
661 }\r
662\r
663 if (!AllChildrenStopped) {\r
664 return EFI_DEVICE_ERROR;\r
665 }\r
666\r
667 return EFI_SUCCESS;\r
668}\r
669\r
670EFI_DEVICE_PATH_PROTOCOL *\r
671UnixBusCreateDevicePath (\r
672 IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath,\r
673 IN EFI_GUID *Guid,\r
674 IN UINT16 InstanceNumber\r
675 )\r
676/*++\r
677\r
678Routine Description:\r
679 Create a device path node using Guid and InstanceNumber and append it to\r
680 the passed in RootDevicePath\r
681\r
682Arguments:\r
683 RootDevicePath - Root of the device path to return.\r
684\r
685 Guid - GUID to use in vendor device path node.\r
686\r
687 InstanceNumber - Instance number to use in the vendor device path. This\r
688 argument is needed to make sure each device path is unique.\r
689\r
690Returns:\r
691\r
692 EFI_DEVICE_PATH_PROTOCOL \r
693\r
694--*/\r
695{\r
696 UNIX_VENDOR_DEVICE_PATH_NODE DevicePath;\r
697\r
698 DevicePath.VendorDevicePath.Header.Type = HARDWARE_DEVICE_PATH;\r
699 DevicePath.VendorDevicePath.Header.SubType = HW_VENDOR_DP;\r
700 SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (UNIX_VENDOR_DEVICE_PATH_NODE));\r
701\r
702 //\r
703 // The GUID defines the Class\r
704 //\r
705 CopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID));\r
706\r
707 //\r
708 // Add an instance number so we can make sure there are no Device Path\r
709 // duplication.\r
710 //\r
711 DevicePath.Instance = InstanceNumber;\r
712\r
713 return AppendDevicePathNode (\r
714 RootDevicePath,\r
715 (EFI_DEVICE_PATH_PROTOCOL *) &DevicePath\r
716 );\r
717}\r