]> git.proxmox.com Git - mirror_edk2.git/blame - EdkUnixPkg/Dxe/UnixThunk/Bus/UnixBusDriver/UnixBusDriver.c
Add emulated serialIo device driver for EdkUnixPkg
[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
377fc2ae 18This following section documents the envirnoment variables for the Win UNIX \r
c9093a06 19build. These variables are used to define the (virtual) hardware \r
377fc2ae 20configuration of the UNIX environment\r
c9093a06 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
377fc2ae 38 UNIX envirnonment variable contents. '<' and '>' are not part of the variable, \r
c9093a06 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
377fc2ae 58 Physical Disks: These devices use UNIX to open a real device in your system\r
c9093a06 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
8ef571df 100 0x419f582, 0x625, 0x4531, {0x8a, 0x33, 0x85, 0xa9, 0x96, 0x5c, 0x95, 0xbc}\r
c9093a06 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
caea5554 110 0xa,\r
c9093a06 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
377fc2ae 118// Table to map UNIX Environment variable to the GUID that should be in\r
c9093a06 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
b19cfa69 125 {PcdToken(PcdUnixSerialPort), &gEfiUnixSerialPortGuid},\r
c9093a06 126 {PcdToken(PcdUnixVirtualDisk), &gEfiUnixVirtualDisksGuid},\r
127 {PcdToken(PcdUnixPhysicalDisk), &gEfiUnixPhysicalDisksGuid},\r
128 {PcdToken(PcdUnixCpuModel), &gEfiUnixCPUModelGuid},\r
129 {PcdToken(PcdUnixCpuSpeed), &gEfiUnixCPUSpeedGuid},\r
130 {PcdToken(PcdUnixMemorySize), &gEfiUnixMemoryGuid}\r
131};\r
132\r
133VOID *\r
134AllocateMemory (\r
135 IN UINTN Size\r
136 )\r
137{\r
138 EFI_STATUS Status;\r
139 VOID *Buffer;\r
140\r
141 Status = gBS->AllocatePool (\r
142 EfiBootServicesData,\r
143 Size,\r
144 (VOID *)&Buffer\r
145 );\r
146 if (EFI_ERROR (Status)) {\r
147 ASSERT (FALSE);\r
148 return NULL;\r
149 }\r
150 return Buffer;\r
151}\r
152\r
153\r
154EFI_STATUS\r
155EFIAPI\r
156UnixBusDriverBindingSupported (\r
157 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
158 IN EFI_HANDLE ControllerHandle,\r
159 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
160 )\r
161/*++\r
162\r
163Routine Description:\r
164\r
165Arguments:\r
166\r
167Returns:\r
168\r
169 None\r
170\r
171--*/\r
172// TODO: This - add argument and description to function comment\r
173// TODO: ControllerHandle - add argument and description to function comment\r
174// TODO: RemainingDevicePath - add argument and description to function comment\r
175// TODO: EFI_UNSUPPORTED - add return value to function comment\r
176// TODO: EFI_UNSUPPORTED - add return value to function comment\r
177// TODO: EFI_SUCCESS - add return value to function comment\r
178// TODO: EFI_SUCCESS - add return value to function comment\r
179{\r
180 EFI_STATUS Status;\r
181 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
182 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;\r
183 UINTN Index;\r
184\r
185 //\r
186 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure\r
187 // it is a legal Device Path Node for this bus driver's children.\r
188 //\r
189 if (RemainingDevicePath != NULL) {\r
190 if (RemainingDevicePath->Type != HARDWARE_DEVICE_PATH ||\r
191 RemainingDevicePath->SubType != HW_VENDOR_DP ||\r
192 DevicePathNodeLength(RemainingDevicePath) != sizeof(UNIX_VENDOR_DEVICE_PATH_NODE)) {\r
193 return EFI_UNSUPPORTED;\r
194 }\r
195\r
196 for (Index = 0; Index < UNIX_PCD_ARRAY_SIZE; Index++) {\r
197 if (CompareGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid, mPcdEnvironment[Index].DevicePathGuid)) {\r
198 break;\r
199 }\r
200 }\r
201\r
202 if (Index >= UNIX_PCD_ARRAY_SIZE) {\r
203 return EFI_UNSUPPORTED;\r
204 }\r
205 }\r
206 \r
207 //\r
208 // Open the IO Abstraction(s) needed to perform the supported test\r
209 //\r
210 Status = gBS->OpenProtocol (\r
211 ControllerHandle,\r
212 &gEfiDevicePathProtocolGuid,\r
213 (VOID **)&ParentDevicePath,\r
214 This->DriverBindingHandle,\r
215 ControllerHandle,\r
216 EFI_OPEN_PROTOCOL_BY_DRIVER\r
217 );\r
218 if (Status == EFI_ALREADY_STARTED) {\r
219 return EFI_SUCCESS;\r
220 }\r
221\r
222 if (EFI_ERROR (Status)) {\r
223 return Status;\r
224 }\r
225\r
226 gBS->CloseProtocol (\r
227 ControllerHandle,\r
228 &gEfiDevicePathProtocolGuid,\r
229 This->DriverBindingHandle,\r
230 ControllerHandle\r
231 );\r
232\r
233 Status = gBS->OpenProtocol (\r
234 ControllerHandle,\r
235 &gEfiUnixThunkProtocolGuid,\r
236 (VOID **)&UnixThunk,\r
237 This->DriverBindingHandle,\r
238 ControllerHandle,\r
239 EFI_OPEN_PROTOCOL_BY_DRIVER\r
240 );\r
241 if (Status == EFI_ALREADY_STARTED) {\r
242 return EFI_SUCCESS;\r
243 }\r
244\r
245 if (EFI_ERROR (Status)) {\r
246 return Status;\r
247 }\r
248\r
249 //\r
250 // Since we call through UnixThunk we need to make sure it's valid\r
251 //\r
252 Status = EFI_SUCCESS;\r
253 if (UnixThunk->Signature != EFI_UNIX_THUNK_PROTOCOL_SIGNATURE) {\r
254 Status = EFI_UNSUPPORTED;\r
255 }\r
256\r
257 //\r
258 // Close the I/O Abstraction(s) used to perform the supported test\r
259 //\r
260 gBS->CloseProtocol (\r
261 ControllerHandle,\r
262 &gEfiUnixThunkProtocolGuid,\r
263 This->DriverBindingHandle,\r
264 ControllerHandle\r
265 );\r
266\r
267 return Status;\r
268}\r
269\r
270EFI_STATUS\r
271EFIAPI\r
272UnixBusDriverBindingStart (\r
273 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
274 IN EFI_HANDLE ControllerHandle,\r
275 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
276 )\r
277/*++\r
278\r
279Routine Description:\r
280\r
281Arguments:\r
282\r
283Returns:\r
284\r
285 None\r
286\r
287--*/\r
288// TODO: This - add argument and description to function comment\r
289// TODO: ControllerHandle - add argument and description to function comment\r
290// TODO: RemainingDevicePath - add argument and description to function comment\r
291// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
292// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
293// TODO: EFI_SUCCESS - add return value to function comment\r
294{\r
295 EFI_STATUS Status;\r
296 EFI_STATUS InstallStatus;\r
b19cfa69 297 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;\r
c9093a06 298 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
b19cfa69 299 UNIX_BUS_DEVICE *UnixBusDevice;\r
300 UNIX_IO_DEVICE *UnixDevice;\r
c9093a06 301 UINTN Index;\r
302 CHAR16 *StartString;\r
303 CHAR16 *SubString;\r
304 UINT16 Count;\r
305 UINTN StringSize;\r
306 UINT16 ComponentName[MAX_UNIX_ENVIRNMENT_VARIABLE_LENGTH];\r
307 UNIX_VENDOR_DEVICE_PATH_NODE *Node;\r
308 BOOLEAN CreateDevice;\r
309 CHAR16 *TempStr;\r
310 CHAR16 *PcdTempStr;\r
311 UINTN TempStrSize;\r
312\r
313 Status = EFI_UNSUPPORTED;\r
314\r
315 //\r
316 // Grab the protocols we need\r
317 //\r
318 Status = gBS->OpenProtocol (\r
319 ControllerHandle,\r
320 &gEfiDevicePathProtocolGuid,\r
321 (VOID **)&ParentDevicePath,\r
322 This->DriverBindingHandle,\r
323 ControllerHandle,\r
324 EFI_OPEN_PROTOCOL_BY_DRIVER\r
325 );\r
326 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
327 return Status;\r
328 }\r
329\r
330 Status = gBS->OpenProtocol (\r
331 ControllerHandle,\r
332 &gEfiUnixThunkProtocolGuid,\r
333 (VOID **)&UnixThunk,\r
334 This->DriverBindingHandle,\r
335 ControllerHandle,\r
336 EFI_OPEN_PROTOCOL_BY_DRIVER\r
337 );\r
338 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
339 return Status;\r
340 }\r
341\r
342 if (Status != EFI_ALREADY_STARTED) {\r
343 Status = gBS->AllocatePool (\r
344 EfiBootServicesData,\r
345 sizeof (UNIX_BUS_DEVICE),\r
346 (VOID *) &UnixBusDevice\r
347 );\r
348 if (EFI_ERROR (Status)) {\r
349 return Status;\r
350 }\r
351\r
352 UnixBusDevice->Signature = UNIX_BUS_DEVICE_SIGNATURE;\r
353 UnixBusDevice->ControllerNameTable = NULL;\r
354\r
355 AddUnicodeString (\r
356 "eng",\r
357 gUnixBusDriverComponentName.SupportedLanguages,\r
358 &UnixBusDevice->ControllerNameTable,\r
359 L"Unix Bus Controller"\r
360 );\r
361\r
362 Status = gBS->InstallMultipleProtocolInterfaces (\r
363 &ControllerHandle,\r
364 &gUnixBusDriverGuid,\r
365 UnixBusDevice,\r
366 NULL\r
367 );\r
368 if (EFI_ERROR (Status)) {\r
369 FreeUnicodeStringTable (UnixBusDevice->ControllerNameTable);\r
370 gBS->FreePool (UnixBusDevice);\r
371 return Status;\r
372 }\r
373 }\r
374\r
375 //\r
376 // Loop on the Variable list. Parse each variable to produce a set of handles that\r
377 // represent virtual hardware devices.\r
378 //\r
379 InstallStatus = EFI_NOT_FOUND;\r
380 for (Index = 0; Index < UNIX_PCD_ARRAY_SIZE; Index++) {\r
381 PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token);\r
382 ASSERT (PcdTempStr != NULL);\r
383\r
384 TempStrSize = StrLen (PcdTempStr);\r
385 TempStr = AllocateMemory ((TempStrSize * sizeof (CHAR16)) + 1);\r
386 StrCpy (TempStr, PcdTempStr);\r
387\r
388 StartString = TempStr;\r
389\r
390 //\r
391 // Parse the envirnment variable into sub strings using '!' as a delimator.\r
392 // Each substring needs it's own handle to be added to the system. This code\r
393 // does not understand the sub string. Thats the device drivers job.\r
394 //\r
395 Count = 0;\r
396 while (*StartString != '\0') {\r
397\r
398 //\r
399 // Find the end of the sub string\r
400 //\r
401 SubString = StartString;\r
402 while (*SubString != '\0' && *SubString != '!') {\r
403 SubString++;\r
404 }\r
405\r
406 if (*SubString == '!') {\r
407 //\r
408 // Replace token with '\0' to make sub strings. If this is the end\r
409 // of the string SubString will already point to NULL.\r
410 //\r
411 *SubString = '\0';\r
412 SubString++;\r
413 }\r
414\r
415 CreateDevice = TRUE;\r
416 if (RemainingDevicePath != NULL) {\r
417 CreateDevice = FALSE;\r
418 Node = (UNIX_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;\r
419 if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&\r
420 Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&\r
421 DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (UNIX_VENDOR_DEVICE_PATH_NODE)\r
422 ) {\r
423 if (CompareGuid (&Node->VendorDevicePath.Guid, mPcdEnvironment[Index].DevicePathGuid) &&\r
424 Node->Instance == Count\r
425 ) {\r
426 CreateDevice = TRUE;\r
427 }\r
428 }\r
429 }\r
430\r
431 if (CreateDevice) {\r
c9093a06 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
b19cfa69 444 UnixDevice->UnixIo.UnixThunk = UnixThunk;\r
c9093a06 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
caea5554 457 // FIXME: check size\r
c9093a06 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