]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/WinNtBusDriverDxe/WinNtBusDriver.c
Check in library class of SalLib.
[mirror_edk2.git] / Nt32Pkg / WinNtBusDriverDxe / WinNtBusDriver.c
CommitLineData
420fc8e5 1/*+++\r
2\r
3Copyright (c) 2006 - 2007, 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 WinNtBusDriver.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_WIN_NT_PHYSICAL_DISKS - maps to drives on your system\r
26EFI_WIN_NT_VIRTUAL_DISKS - maps to a device emulated by a file\r
27EFI_WIN_NT_FILE_SYSTEM - mouts a directory as a file system\r
28EFI_WIN_NT_CONSOLE - make a logical comand line window (only one!)\r
29EFI_WIN_NT_UGA - Builds UGA Windows of Width and Height\r
30EFI_WIN_NT_SERIAL_PORT - maps physical serial ports\r
31\r
32 <F>ixed - Fixed disk like a hard drive.\r
33 <R>emovable - Removable media like a floppy or CD-ROM.\r
34 Read <O>nly - Write protected device.\r
35 Read <W>rite - Read write device.\r
36 <block count> - Decimal number of blocks a device supports.\r
37 <block size> - Decimal number of bytes per block.\r
38\r
39 NT envirnonment variable contents. '<' and '>' are not part of the variable,\r
40 they are just used to make this help more readable. There should be no\r
41 spaces between the ';'. Extra spaces will break the variable. A '!' is\r
42 used to seperate multiple devices in a variable.\r
43\r
44 EFI_WIN_NT_VIRTUAL_DISKS =\r
45 <F | R><O | W>;<block count>;<block size>[!...]\r
46\r
47 EFI_WIN_NT_PHYSICAL_DISKS =\r
48 <drive letter>:<F | R><O | W>;<block count>;<block size>[!...]\r
49\r
50 Virtual Disks: These devices use a file to emulate a hard disk or removable\r
51 media device.\r
52\r
53 Thus a 20 MB emulated hard drive would look like:\r
54 EFI_WIN_NT_VIRTUAL_DISKS=FW;40960;512\r
55\r
56 A 1.44MB emulated floppy with a block size of 1024 would look like:\r
57 EFI_WIN_NT_VIRTUAL_DISKS=RW;1440;1024\r
58\r
59 Physical Disks: These devices use NT to open a real device in your system\r
60\r
61 Thus a 120 MB floppy would look like:\r
62 EFI_WIN_NT_PHYSICAL_DISKS=B:RW;245760;512\r
63\r
64 Thus a standard CD-ROM floppy would look like:\r
65 EFI_WIN_NT_PHYSICAL_DISKS=Z:RO;307200;2048\r
66\r
67 EFI_WIN_NT_FILE_SYSTEM =\r
68 <directory path>[!...]\r
69\r
70 Mounting the two directories C:\FOO and C:\BAR would look like:\r
71 EFI_WIN_NT_FILE_SYSTEM=c:\foo!c:\bar\r
72\r
73 EFI_WIN_NT_CONSOLE =\r
74 <window title>\r
75\r
76 Declaring a text console window with the title "My EFI Console" woild look like:\r
77 EFI_WIN_NT_CONSOLE=My EFI Console\r
78\r
79 EFI_WIN_NT_UGA =\r
80 <width> <height>[!...]\r
81\r
82 Declaring a two UGA windows with resolutions of 800x600 and 1024x768 would look like:\r
83 Example : EFI_WIN_NT_UGA=800 600!1024 768\r
84\r
85 EFI_WIN_NT_SERIAL_PORT =\r
86 <port name>[!...]\r
87\r
88 Declaring two serial ports on COM1 and COM2 would look like:\r
89 Example : EFI_WIN_NT_SERIAL_PORT=COM1!COM2\r
90\r
91 EFI_WIN_NT_PASS_THROUGH =\r
92 <BaseAddress>;<Bus#>;<Device#>;<Function#>\r
93\r
94 Declaring a base address of 0xE0000000 (used for PCI Express devices)\r
95 and having NT32 talk to a device located at bus 0, device 1, function 0:\r
96 Example : EFI_WIN_NT_PASS_THROUGH=E000000;0;1;0\r
97\r
98---*/\r
99\r
100//\r
101// The package level header files this module uses\r
102//\r
103#include <Uefi.h>\r
104#include <WinNtDxe.h>\r
105//\r
106// The protocols, PPI and GUID defintions for this module\r
107//\r
108#include <Protocol/WinNtThunk.h>\r
109#include <Protocol/WinNtIo.h>\r
110#include <Protocol/ComponentName.h>\r
111#include <Protocol/DriverBinding.h>\r
112#include <Protocol/DevicePath.h>\r
113//\r
114// The Library classes this module consumes\r
115//\r
116#include <Library/DebugLib.h>\r
117#include <Library/BaseLib.h>\r
118#include <Library/UefiDriverEntryPoint.h>\r
119#include <Library/UefiLib.h>\r
120#include <Library/PcdLib.h>\r
121#include <Library/BaseMemoryLib.h>\r
122#include <Library/UefiBootServicesTableLib.h>\r
123#include <Library/DevicePathLib.h>\r
124#include <Library/MemoryAllocationLib.h>\r
125\r
126#include "WinNtBusDriver.h"\r
127\r
128extern EFI_GUID gWinNtBusDriverGuid;\r
129//\r
130// DriverBinding protocol global\r
131//\r
132EFI_DRIVER_BINDING_PROTOCOL gWinNtBusDriverBinding = {\r
133 WinNtBusDriverBindingSupported,\r
134 WinNtBusDriverBindingStart,\r
135 WinNtBusDriverBindingStop,\r
136 0xa,\r
137 NULL,\r
138 NULL\r
139};\r
140\r
141#define NT_PCD_ARRAY_SIZE (sizeof(mPcdEnvironment)/sizeof(NT_PCD_ENTRY))\r
142\r
143//\r
144// Table to map NT Environment variable to the GUID that should be in\r
145// device path.\r
146//\r
147static NT_PCD_ENTRY mPcdEnvironment[] = {\r
148 PcdToken(PcdWinNtConsole), &gEfiWinNtConsoleGuid,\r
149 PcdToken(PcdWinNtGop), &gEfiWinNtGopGuid,\r
150 PcdToken(PcdWinNtSerialPort), &gEfiWinNtSerialPortGuid,\r
151 PcdToken(PcdWinNtFileSystem), &gEfiWinNtFileSystemGuid,\r
152 PcdToken(PcdWinNtVirtualDisk), &gEfiWinNtVirtualDisksGuid,\r
153 PcdToken(PcdWinNtPhysicalDisk), &gEfiWinNtPhysicalDisksGuid,\r
154 PcdToken(PcdWinNtCpuModel), &gEfiWinNtCPUModelGuid,\r
155 PcdToken(PcdWinNtCpuSpeed), &gEfiWinNtCPUSpeedGuid,\r
156 PcdToken(PcdWinNtMemorySize), &gEfiWinNtMemoryGuid\r
157};\r
158\r
159/**\r
160 The user Entry Point for module WinNtBusDriver. The user code starts with this function.\r
161\r
162 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
163 @param[in] SystemTable A pointer to the EFI System Table.\r
164 \r
165 @retval EFI_SUCCESS The entry point is executed successfully.\r
166 @retval other Some error occurs when executing this entry point.\r
167\r
168**/\r
169EFI_STATUS\r
170EFIAPI\r
171InitializeWinNtBusDriver(\r
172 IN EFI_HANDLE ImageHandle,\r
173 IN EFI_SYSTEM_TABLE *SystemTable\r
174 )\r
175{\r
176 EFI_STATUS Status;\r
177\r
178 //\r
179 // Install driver model protocol(s).\r
180 //\r
181 Status = EfiLibInstallAllDriverProtocols (\r
182 ImageHandle,\r
183 SystemTable,\r
184 &gWinNtBusDriverBinding,\r
185 ImageHandle,\r
186 &gWinNtBusDriverComponentName,\r
187 NULL,\r
188 NULL\r
189 );\r
190 ASSERT_EFI_ERROR (Status);\r
191\r
192\r
193 return Status;\r
194}\r
195\r
196VOID *\r
197AllocateMemory (\r
198 IN UINTN Size\r
199 )\r
200{\r
201 VOID *Buffer;\r
202\r
203 Buffer = AllocatePool (Size);\r
204 ASSERT (Buffer != NULL);\r
205\r
206 return Buffer;\r
207}\r
208\r
209\r
210EFI_STATUS\r
211EFIAPI\r
212WinNtBusDriverBindingSupported (\r
213 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
214 IN EFI_HANDLE ControllerHandle,\r
215 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
216 )\r
217/*++\r
218\r
219Routine Description:\r
220\r
221Arguments:\r
222\r
223Returns:\r
224\r
225 None\r
226\r
227--*/\r
228// TODO: This - add argument and description to function comment\r
229// TODO: ControllerHandle - add argument and description to function comment\r
230// TODO: RemainingDevicePath - add argument and description to function comment\r
231// TODO: EFI_UNSUPPORTED - add return value to function comment\r
232// TODO: EFI_UNSUPPORTED - add return value to function comment\r
233// TODO: EFI_SUCCESS - add return value to function comment\r
234// TODO: EFI_SUCCESS - add return value to function comment\r
235{\r
236 EFI_STATUS Status;\r
237 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
238 EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk;\r
239 UINTN Index;\r
240\r
241 //\r
242 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure\r
243 // it is a legal Device Path Node for this bus driver's children.\r
244 //\r
245 if (RemainingDevicePath != NULL) {\r
246 if (RemainingDevicePath->Type != HARDWARE_DEVICE_PATH ||\r
247 RemainingDevicePath->SubType != HW_VENDOR_DP ||\r
248 DevicePathNodeLength(RemainingDevicePath) != sizeof(WIN_NT_VENDOR_DEVICE_PATH_NODE)) {\r
249 return EFI_UNSUPPORTED;\r
250 }\r
251\r
252 for (Index = 0; Index < NT_PCD_ARRAY_SIZE; Index++) {\r
253 if (CompareGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid, mPcdEnvironment[Index].DevicePathGuid)) {\r
254 break;\r
255 }\r
256 }\r
257\r
258 if (Index >= NT_PCD_ARRAY_SIZE) {\r
259 return EFI_UNSUPPORTED;\r
260 }\r
261 }\r
262\r
263 //\r
264 // Open the IO Abstraction(s) needed to perform the supported test\r
265 //\r
266 Status = gBS->OpenProtocol (\r
267 ControllerHandle,\r
268 &gEfiDevicePathProtocolGuid,\r
269 &ParentDevicePath,\r
270 This->DriverBindingHandle,\r
271 ControllerHandle,\r
272 EFI_OPEN_PROTOCOL_BY_DRIVER\r
273 );\r
274 if (Status == EFI_ALREADY_STARTED) {\r
275 return EFI_SUCCESS;\r
276 }\r
277\r
278 if (EFI_ERROR (Status)) {\r
279 return Status;\r
280 }\r
281\r
282 gBS->CloseProtocol (\r
283 ControllerHandle,\r
284 &gEfiDevicePathProtocolGuid,\r
285 This->DriverBindingHandle,\r
286 ControllerHandle\r
287 );\r
288\r
289 Status = gBS->OpenProtocol (\r
290 ControllerHandle,\r
291 &gEfiWinNtThunkProtocolGuid,\r
292 &WinNtThunk,\r
293 This->DriverBindingHandle,\r
294 ControllerHandle,\r
295 EFI_OPEN_PROTOCOL_BY_DRIVER\r
296 );\r
297 if (Status == EFI_ALREADY_STARTED) {\r
298 return EFI_SUCCESS;\r
299 }\r
300\r
301 if (EFI_ERROR (Status)) {\r
302 return Status;\r
303 }\r
304\r
305 //\r
306 // Since we call through WinNtThunk we need to make sure it's valid\r
307 //\r
308 Status = EFI_SUCCESS;\r
309 if (WinNtThunk->Signature != EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) {\r
310 Status = EFI_UNSUPPORTED;\r
311 }\r
312\r
313 //\r
314 // Close the I/O Abstraction(s) used to perform the supported test\r
315 //\r
316 gBS->CloseProtocol (\r
317 ControllerHandle,\r
318 &gEfiWinNtThunkProtocolGuid,\r
319 This->DriverBindingHandle,\r
320 ControllerHandle\r
321 );\r
322\r
323 return Status;\r
324}\r
325\r
326EFI_STATUS\r
327EFIAPI\r
328WinNtBusDriverBindingStart (\r
329 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
330 IN EFI_HANDLE ControllerHandle,\r
331 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
332 )\r
333/*++\r
334\r
335Routine Description:\r
336\r
337Arguments:\r
338\r
339Returns:\r
340\r
341 None\r
342\r
343--*/\r
344// TODO: This - add argument and description to function comment\r
345// TODO: ControllerHandle - add argument and description to function comment\r
346// TODO: RemainingDevicePath - add argument and description to function comment\r
347// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
348// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
349// TODO: EFI_SUCCESS - add return value to function comment\r
350{\r
351 EFI_STATUS Status;\r
352 EFI_STATUS InstallStatus;\r
353 EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk;\r
354 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
355 WIN_NT_BUS_DEVICE *WinNtBusDevice;\r
356 WIN_NT_IO_DEVICE *WinNtDevice;\r
357 UINTN Index;\r
358 CHAR16 *StartString;\r
359 CHAR16 *SubString;\r
360 UINT16 Count;\r
361 UINTN StringSize;\r
362 UINT16 ComponentName[MAX_NT_ENVIRNMENT_VARIABLE_LENGTH];\r
363 WIN_NT_VENDOR_DEVICE_PATH_NODE *Node;\r
364 BOOLEAN CreateDevice;\r
365 CHAR16 *TempStr;\r
366 CHAR16 *PcdTempStr;\r
367 UINTN TempStrSize;\r
368\r
369 Status = EFI_UNSUPPORTED;\r
370\r
371 //\r
372 // Grab the protocols we need\r
373 //\r
374 Status = gBS->OpenProtocol (\r
375 ControllerHandle,\r
376 &gEfiDevicePathProtocolGuid,\r
377 &ParentDevicePath,\r
378 This->DriverBindingHandle,\r
379 ControllerHandle,\r
380 EFI_OPEN_PROTOCOL_BY_DRIVER\r
381 );\r
382 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
383 return Status;\r
384 }\r
385\r
386 Status = gBS->OpenProtocol (\r
387 ControllerHandle,\r
388 &gEfiWinNtThunkProtocolGuid,\r
389 &WinNtThunk,\r
390 This->DriverBindingHandle,\r
391 ControllerHandle,\r
392 EFI_OPEN_PROTOCOL_BY_DRIVER\r
393 );\r
394 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
395 return Status;\r
396 }\r
397\r
398 if (Status != EFI_ALREADY_STARTED) {\r
399 WinNtBusDevice = AllocatePool (sizeof (WIN_NT_BUS_DEVICE));\r
400 if (WinNtBusDevice == NULL) {\r
401 return EFI_OUT_OF_RESOURCES;\r
402 }\r
403\r
404 WinNtBusDevice->Signature = WIN_NT_BUS_DEVICE_SIGNATURE;\r
405 WinNtBusDevice->ControllerNameTable = NULL;\r
406\r
407 AddUnicodeString (\r
408 "eng",\r
409 gWinNtBusDriverComponentName.SupportedLanguages,\r
410 &WinNtBusDevice->ControllerNameTable,\r
411 L"Windows Bus Controller"\r
412 );\r
413\r
414 Status = gBS->InstallMultipleProtocolInterfaces (\r
415 &ControllerHandle,\r
416 &gWinNtBusDriverGuid,\r
417 WinNtBusDevice,\r
418 NULL\r
419 );\r
420 if (EFI_ERROR (Status)) {\r
421 FreeUnicodeStringTable (WinNtBusDevice->ControllerNameTable);\r
422 FreePool (WinNtBusDevice);\r
423 return Status;\r
424 }\r
425 }\r
426\r
427 //\r
428 // Loop on the Variable list. Parse each variable to produce a set of handles that\r
429 // represent virtual hardware devices.\r
430 //\r
431 InstallStatus = EFI_NOT_FOUND;\r
432 for (Index = 0; Index < NT_PCD_ARRAY_SIZE; Index++) {\r
433 PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token);\r
434 ASSERT (PcdTempStr != NULL);\r
435\r
436 TempStrSize = StrLen (PcdTempStr);\r
437 TempStr = AllocateMemory ((TempStrSize * sizeof (CHAR16)) + 1);\r
438 StrCpy (TempStr, PcdTempStr);\r
439\r
440 StartString = TempStr;\r
441\r
442 //\r
443 // Parse the envirnment variable into sub strings using '!' as a delimator.\r
444 // Each substring needs it's own handle to be added to the system. This code\r
445 // does not understand the sub string. Thats the device drivers job.\r
446 //\r
447 Count = 0;\r
448 while (*StartString != '\0') {\r
449\r
450 //\r
451 // Find the end of the sub string\r
452 //\r
453 SubString = StartString;\r
454 while (*SubString != '\0' && *SubString != '!') {\r
455 SubString++;\r
456 }\r
457\r
458 if (*SubString == '!') {\r
459 //\r
460 // Replace token with '\0' to make sub strings. If this is the end\r
461 // of the string SubString will already point to NULL.\r
462 //\r
463 *SubString = '\0';\r
464 SubString++;\r
465 }\r
466\r
467 CreateDevice = TRUE;\r
468 if (RemainingDevicePath != NULL) {\r
469 CreateDevice = FALSE;\r
470 Node = (WIN_NT_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;\r
471 if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&\r
472 Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&\r
473 DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)\r
474 ) {\r
475 if (CompareGuid (&Node->VendorDevicePath.Guid, mPcdEnvironment[Index].DevicePathGuid) &&\r
476 Node->Instance == Count\r
477 ) {\r
478 CreateDevice = TRUE;\r
479 }\r
480 }\r
481 }\r
482\r
483 if (CreateDevice) {\r
484\r
485 //\r
486 // Allocate instance structure, and fill in parent information.\r
487 //\r
488 WinNtDevice = AllocateMemory (sizeof (WIN_NT_IO_DEVICE));\r
489 if (WinNtDevice == NULL) {\r
490 return EFI_OUT_OF_RESOURCES;\r
491 }\r
492\r
493 WinNtDevice->Handle = NULL;\r
494 WinNtDevice->ControllerHandle = ControllerHandle;\r
495 WinNtDevice->ParentDevicePath = ParentDevicePath;\r
496\r
497 WinNtDevice->WinNtIo.WinNtThunk = WinNtThunk;\r
498\r
499 //\r
500 // Plus 2 to account for the NULL at the end of the Unicode string\r
501 //\r
502 StringSize = (UINTN) ((UINT8 *) SubString - (UINT8 *) StartString) + sizeof (CHAR16);\r
503 WinNtDevice->WinNtIo.EnvString = AllocateMemory (StringSize);\r
504 if (WinNtDevice->WinNtIo.EnvString != NULL) {\r
505 CopyMem (WinNtDevice->WinNtIo.EnvString, StartString, StringSize);\r
506 }\r
507\r
508 WinNtDevice->ControllerNameTable = NULL;\r
509\r
510 WinNtThunk->SPrintf (ComponentName, sizeof (ComponentName), L"%s", WinNtDevice->WinNtIo.EnvString);\r
511\r
512 WinNtDevice->DevicePath = WinNtBusCreateDevicePath (\r
513 ParentDevicePath,\r
514 mPcdEnvironment[Index].DevicePathGuid,\r
515 Count\r
516 );\r
517 if (WinNtDevice->DevicePath == NULL) {\r
518 FreePool (WinNtDevice);\r
519 return EFI_OUT_OF_RESOURCES;\r
520 }\r
521\r
522 AddUnicodeString (\r
523 "eng",\r
524 gWinNtBusDriverComponentName.SupportedLanguages,\r
525 &WinNtDevice->ControllerNameTable,\r
526 ComponentName\r
527 );\r
528\r
529 WinNtDevice->WinNtIo.TypeGuid = mPcdEnvironment[Index].DevicePathGuid;\r
530 WinNtDevice->WinNtIo.InstanceNumber = Count;\r
531\r
532 WinNtDevice->Signature = WIN_NT_IO_DEVICE_SIGNATURE;\r
533\r
534 Status = gBS->InstallMultipleProtocolInterfaces (\r
535 &WinNtDevice->Handle,\r
536 &gEfiDevicePathProtocolGuid,\r
537 WinNtDevice->DevicePath,\r
538 &gEfiWinNtIoProtocolGuid,\r
539 &WinNtDevice->WinNtIo,\r
540 NULL\r
541 );\r
542 if (EFI_ERROR (Status)) {\r
543 FreeUnicodeStringTable (WinNtDevice->ControllerNameTable);\r
544 FreePool (WinNtDevice);\r
545 } else {\r
546 //\r
547 // Open For Child Device\r
548 //\r
549 Status = gBS->OpenProtocol (\r
550 ControllerHandle,\r
551 &gEfiWinNtThunkProtocolGuid,\r
552 &WinNtThunk,\r
553 This->DriverBindingHandle,\r
554 WinNtDevice->Handle,\r
555 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
556 );\r
557 if (!EFI_ERROR (Status)) {\r
558 InstallStatus = EFI_SUCCESS;\r
559 }\r
560 }\r
561 }\r
562\r
563 //\r
564 // Parse Next sub string. This will point to '\0' if we are at the end.\r
565 //\r
566 Count++;\r
567 StartString = SubString;\r
568 }\r
569\r
570 FreePool (TempStr);\r
571 }\r
572\r
573 return EFI_SUCCESS;\r
574}\r
575\r
576\r
577EFI_STATUS\r
578EFIAPI\r
579WinNtBusDriverBindingStop (\r
580 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
581 IN EFI_HANDLE ControllerHandle,\r
582 IN UINTN NumberOfChildren,\r
583 IN EFI_HANDLE *ChildHandleBuffer\r
584 )\r
585/*++\r
586\r
587Routine Description:\r
588\r
589Arguments:\r
590\r
591Returns:\r
592\r
593 None\r
594\r
595--*/\r
596// TODO: This - add argument and description to function comment\r
597// TODO: ControllerHandle - add argument and description to function comment\r
598// TODO: NumberOfChildren - add argument and description to function comment\r
599// TODO: ChildHandleBuffer - add argument and description to function comment\r
600// TODO: EFI_SUCCESS - add return value to function comment\r
601// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
602// TODO: EFI_SUCCESS - add return value to function comment\r
603{\r
604 EFI_STATUS Status;\r
605 UINTN Index;\r
606 BOOLEAN AllChildrenStopped;\r
607 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
608 WIN_NT_BUS_DEVICE *WinNtBusDevice;\r
609 WIN_NT_IO_DEVICE *WinNtDevice;\r
610 EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk;\r
611\r
612 //\r
613 // Complete all outstanding transactions to Controller.\r
614 // Don't allow any new transaction to Controller to be started.\r
615 //\r
616\r
617 if (NumberOfChildren == 0) {\r
618 //\r
619 // Close the bus driver\r
620 //\r
621 Status = gBS->OpenProtocol (\r
622 ControllerHandle,\r
623 &gWinNtBusDriverGuid,\r
624 &WinNtBusDevice,\r
625 This->DriverBindingHandle,\r
626 ControllerHandle,\r
627 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
628 );\r
629 if (EFI_ERROR (Status)) {\r
630 return Status;\r
631 }\r
632\r
633 gBS->UninstallMultipleProtocolInterfaces (\r
634 ControllerHandle,\r
635 &gWinNtBusDriverGuid,\r
636 WinNtBusDevice,\r
637 NULL\r
638 );\r
639\r
640 FreeUnicodeStringTable (WinNtBusDevice->ControllerNameTable);\r
641\r
642 FreePool (WinNtBusDevice);\r
643\r
644 gBS->CloseProtocol (\r
645 ControllerHandle,\r
646 &gEfiWinNtThunkProtocolGuid,\r
647 This->DriverBindingHandle,\r
648 ControllerHandle\r
649 );\r
650\r
651 gBS->CloseProtocol (\r
652 ControllerHandle,\r
653 &gEfiDevicePathProtocolGuid,\r
654 This->DriverBindingHandle,\r
655 ControllerHandle\r
656 );\r
657 return EFI_SUCCESS;\r
658 }\r
659\r
660 AllChildrenStopped = TRUE;\r
661\r
662 for (Index = 0; Index < NumberOfChildren; Index++) {\r
663\r
664 Status = gBS->OpenProtocol (\r
665 ChildHandleBuffer[Index],\r
666 &gEfiWinNtIoProtocolGuid,\r
667 &WinNtIo,\r
668 This->DriverBindingHandle,\r
669 ControllerHandle,\r
670 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
671 );\r
672 if (!EFI_ERROR (Status)) {\r
673\r
674 WinNtDevice = WIN_NT_IO_DEVICE_FROM_THIS (WinNtIo);\r
675\r
676 Status = gBS->CloseProtocol (\r
677 ControllerHandle,\r
678 &gEfiWinNtThunkProtocolGuid,\r
679 This->DriverBindingHandle,\r
680 WinNtDevice->Handle\r
681 );\r
682\r
683 Status = gBS->UninstallMultipleProtocolInterfaces (\r
684 WinNtDevice->Handle,\r
685 &gEfiDevicePathProtocolGuid,\r
686 WinNtDevice->DevicePath,\r
687 &gEfiWinNtIoProtocolGuid,\r
688 &WinNtDevice->WinNtIo,\r
689 NULL\r
690 );\r
691\r
692 if (EFI_ERROR (Status)) {\r
693 gBS->OpenProtocol (\r
694 ControllerHandle,\r
695 &gEfiWinNtThunkProtocolGuid,\r
696 (VOID **) &WinNtThunk,\r
697 This->DriverBindingHandle,\r
698 WinNtDevice->Handle,\r
699 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
700 );\r
701 } else {\r
702 //\r
703 // Close the child handle\r
704 //\r
705 FreeUnicodeStringTable (WinNtDevice->ControllerNameTable);\r
706 FreePool (WinNtDevice);\r
707 }\r
708 }\r
709\r
710 if (EFI_ERROR (Status)) {\r
711 AllChildrenStopped = FALSE;\r
712 }\r
713 }\r
714\r
715 if (!AllChildrenStopped) {\r
716 return EFI_DEVICE_ERROR;\r
717 }\r
718\r
719 return EFI_SUCCESS;\r
720}\r
721\r
722EFI_DEVICE_PATH_PROTOCOL *\r
723WinNtBusCreateDevicePath (\r
724 IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath,\r
725 IN EFI_GUID *Guid,\r
726 IN UINT16 InstanceNumber\r
727 )\r
728/*++\r
729\r
730Routine Description:\r
731 Create a device path node using Guid and InstanceNumber and append it to\r
732 the passed in RootDevicePath\r
733\r
734Arguments:\r
735 RootDevicePath - Root of the device path to return.\r
736\r
737 Guid - GUID to use in vendor device path node.\r
738\r
739 InstanceNumber - Instance number to use in the vendor device path. This\r
740 argument is needed to make sure each device path is unique.\r
741\r
742Returns:\r
743\r
744 EFI_DEVICE_PATH_PROTOCOL\r
745\r
746--*/\r
747{\r
748 WIN_NT_VENDOR_DEVICE_PATH_NODE DevicePath;\r
749\r
750 DevicePath.VendorDevicePath.Header.Type = HARDWARE_DEVICE_PATH;\r
751 DevicePath.VendorDevicePath.Header.SubType = HW_VENDOR_DP;\r
752 SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE));\r
753\r
754 //\r
755 // The GUID defines the Class\r
756 //\r
757 CopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID));\r
758\r
759 //\r
760 // Add an instance number so we can make sure there are no Device Path\r
761 // duplication.\r
762 //\r
763 DevicePath.Instance = InstanceNumber;\r
764\r
765 return AppendDevicePathNode (\r
766 RootDevicePath,\r
767 (EFI_DEVICE_PATH_PROTOCOL *) &DevicePath\r
768 );\r
769}\r