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