]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - Nt32Pkg/WinNtBusDriverDxe/WinNtBusDriver.c
Vlv2TbltDevicePkg/PlatformBdsLib: Add DebugAgent Console
[mirror_edk2.git] / Nt32Pkg / WinNtBusDriverDxe / WinNtBusDriver.c
... / ...
CommitLineData
1/**@file\r
2\r
3Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r
4This 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_GOP - Builds GOP 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_GOP =\r
80 <width> <height>[!...]\r
81\r
82 Declaring a two GOP windows with resolutions of 800x600 and 1024x768 would look like:\r
83 Example : EFI_WIN_NT_GOP=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
147NT_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};\r
155\r
156/**\r
157 The user Entry Point for module WinNtBusDriver. The user code starts with this function.\r
158\r
159 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
160 @param[in] SystemTable A pointer to the EFI System Table.\r
161\r
162 @retval EFI_SUCCESS The entry point is executed successfully.\r
163 @retval other Some error occurs when executing this entry point.\r
164\r
165**/\r
166EFI_STATUS\r
167EFIAPI\r
168InitializeWinNtBusDriver(\r
169 IN EFI_HANDLE ImageHandle,\r
170 IN EFI_SYSTEM_TABLE *SystemTable\r
171 )\r
172{\r
173 EFI_STATUS Status;\r
174\r
175 //\r
176 // Install driver model protocol(s).\r
177 //\r
178 Status = EfiLibInstallDriverBindingComponentName2 (\r
179 ImageHandle,\r
180 SystemTable,\r
181 &gWinNtBusDriverBinding,\r
182 ImageHandle,\r
183 &gWinNtBusDriverComponentName,\r
184 &gWinNtBusDriverComponentName2\r
185 );\r
186 ASSERT_EFI_ERROR (Status);\r
187\r
188\r
189 return Status;\r
190}\r
191\r
192VOID *\r
193AllocateMemory (\r
194 IN UINTN Size\r
195 )\r
196{\r
197 VOID *Buffer;\r
198\r
199 Buffer = AllocatePool (Size);\r
200 ASSERT (Buffer != NULL);\r
201\r
202 return Buffer;\r
203}\r
204\r
205\r
206EFI_STATUS\r
207EFIAPI\r
208WinNtBusDriverBindingSupported (\r
209 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
210 IN EFI_HANDLE ControllerHandle,\r
211 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
212 )\r
213/*++\r
214\r
215Routine Description:\r
216\r
217Arguments:\r
218\r
219Returns:\r
220\r
221 None\r
222\r
223**/\r
224// TODO: This - add argument and description to function comment\r
225// TODO: ControllerHandle - add argument and description to function comment\r
226// TODO: RemainingDevicePath - add argument and description to function comment\r
227// TODO: EFI_UNSUPPORTED - add return value to function comment\r
228// TODO: EFI_UNSUPPORTED - add return value to function comment\r
229// TODO: EFI_SUCCESS - add return value to function comment\r
230// TODO: EFI_SUCCESS - add return value to function comment\r
231{\r
232 EFI_STATUS Status;\r
233 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
234 EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk;\r
235 UINTN Index;\r
236\r
237 //\r
238 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure\r
239 // it is a legal Device Path Node for this bus driver's children.\r
240 //\r
241 if (RemainingDevicePath != NULL) {\r
242 //\r
243 // Check if RemainingDevicePath is the End of Device Path Node, \r
244 // if yes, go on checking other conditions\r
245 //\r
246 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
247 //\r
248 // If RemainingDevicePath isn't the End of Device Path Node,\r
249 // check its validation\r
250 //\r
251 if (RemainingDevicePath->Type != HARDWARE_DEVICE_PATH ||\r
252 RemainingDevicePath->SubType != HW_VENDOR_DP ||\r
253 DevicePathNodeLength(RemainingDevicePath) != sizeof(WIN_NT_VENDOR_DEVICE_PATH_NODE)) {\r
254 return EFI_UNSUPPORTED;\r
255 }\r
256 \r
257 for (Index = 0; Index < NT_PCD_ARRAY_SIZE; Index++) {\r
258 if (CompareGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid, mPcdEnvironment[Index].DevicePathGuid)) {\r
259 break;\r
260 }\r
261 }\r
262 \r
263 if (Index >= NT_PCD_ARRAY_SIZE) {\r
264 return EFI_UNSUPPORTED;\r
265 }\r
266 }\r
267 }\r
268\r
269 //\r
270 // Open the IO Abstraction(s) needed to perform the supported test\r
271 //\r
272 Status = gBS->OpenProtocol (\r
273 ControllerHandle,\r
274 &gEfiWinNtThunkProtocolGuid,\r
275 (VOID **) &WinNtThunk,\r
276 This->DriverBindingHandle,\r
277 ControllerHandle,\r
278 EFI_OPEN_PROTOCOL_BY_DRIVER\r
279 );\r
280 if (Status == EFI_ALREADY_STARTED) {\r
281 return EFI_SUCCESS;\r
282 }\r
283\r
284 if (EFI_ERROR (Status)) {\r
285 return Status;\r
286 }\r
287\r
288 //\r
289 // Close the I/O Abstraction(s) used to perform the supported test\r
290 //\r
291 gBS->CloseProtocol (\r
292 ControllerHandle,\r
293 &gEfiWinNtThunkProtocolGuid,\r
294 This->DriverBindingHandle,\r
295 ControllerHandle\r
296 );\r
297\r
298 //\r
299 // Open the EFI Device Path protocol needed to perform the supported test\r
300 //\r
301 Status = gBS->OpenProtocol (\r
302 ControllerHandle,\r
303 &gEfiDevicePathProtocolGuid,\r
304 (VOID **) &ParentDevicePath,\r
305 This->DriverBindingHandle,\r
306 ControllerHandle,\r
307 EFI_OPEN_PROTOCOL_BY_DRIVER\r
308 );\r
309 if (Status == EFI_ALREADY_STARTED) {\r
310 return EFI_SUCCESS;\r
311 }\r
312\r
313 if (EFI_ERROR (Status)) {\r
314 return Status;\r
315 }\r
316\r
317 //\r
318 // Since we call through WinNtThunk we need to make sure it's valid\r
319 //\r
320 Status = EFI_SUCCESS;\r
321 if (WinNtThunk->Signature != EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) {\r
322 Status = EFI_UNSUPPORTED;\r
323 }\r
324\r
325 //\r
326 // Close protocol, don't use device path protocol in the Support() function\r
327 //\r
328 gBS->CloseProtocol (\r
329 ControllerHandle,\r
330 &gEfiDevicePathProtocolGuid,\r
331 This->DriverBindingHandle,\r
332 ControllerHandle\r
333 );\r
334\r
335 return Status;\r
336}\r
337\r
338EFI_STATUS\r
339EFIAPI\r
340WinNtBusDriverBindingStart (\r
341 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
342 IN EFI_HANDLE ControllerHandle,\r
343 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
344 )\r
345/*++\r
346\r
347Routine Description:\r
348\r
349Arguments:\r
350\r
351Returns:\r
352\r
353 None\r
354\r
355--*/\r
356// TODO: This - add argument and description to function comment\r
357// TODO: ControllerHandle - add argument and description to function comment\r
358// TODO: RemainingDevicePath - add argument and description to function comment\r
359// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
360// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
361// TODO: EFI_SUCCESS - add return value to function comment\r
362{\r
363 EFI_STATUS Status;\r
364 EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk;\r
365 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
366 WIN_NT_BUS_DEVICE *WinNtBusDevice;\r
367 WIN_NT_IO_DEVICE *WinNtDevice;\r
368 UINTN Index;\r
369 CHAR16 *StartString;\r
370 CHAR16 *SubString;\r
371 UINT16 Count;\r
372 UINTN StringSize;\r
373 UINT16 ComponentName[MAX_NT_ENVIRNMENT_VARIABLE_LENGTH];\r
374 WIN_NT_VENDOR_DEVICE_PATH_NODE *Node;\r
375 BOOLEAN CreateDevice;\r
376 CHAR16 *TempStr;\r
377 CHAR16 *PcdTempStr;\r
378 UINTN TempStrSize;\r
379\r
380 Status = EFI_UNSUPPORTED;\r
381\r
382 //\r
383 // Grab the protocols we need\r
384 //\r
385 Status = gBS->OpenProtocol (\r
386 ControllerHandle,\r
387 &gEfiDevicePathProtocolGuid,\r
388 (VOID **) &ParentDevicePath,\r
389 This->DriverBindingHandle,\r
390 ControllerHandle,\r
391 EFI_OPEN_PROTOCOL_BY_DRIVER\r
392 );\r
393 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
394 return Status;\r
395 }\r
396\r
397 Status = gBS->OpenProtocol (\r
398 ControllerHandle,\r
399 &gEfiWinNtThunkProtocolGuid,\r
400 (VOID **) &WinNtThunk,\r
401 This->DriverBindingHandle,\r
402 ControllerHandle,\r
403 EFI_OPEN_PROTOCOL_BY_DRIVER\r
404 );\r
405 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
406 return Status;\r
407 }\r
408\r
409 if (Status != EFI_ALREADY_STARTED) {\r
410 WinNtBusDevice = AllocatePool (sizeof (WIN_NT_BUS_DEVICE));\r
411 if (WinNtBusDevice == NULL) {\r
412 return EFI_OUT_OF_RESOURCES;\r
413 }\r
414\r
415 WinNtBusDevice->Signature = WIN_NT_BUS_DEVICE_SIGNATURE;\r
416 WinNtBusDevice->ControllerNameTable = NULL;\r
417\r
418 AddUnicodeString2 (\r
419 "eng",\r
420 gWinNtBusDriverComponentName.SupportedLanguages,\r
421 &WinNtBusDevice->ControllerNameTable,\r
422 L"Windows Bus Controller",\r
423 TRUE\r
424 );\r
425 AddUnicodeString2 (\r
426 "en",\r
427 gWinNtBusDriverComponentName2.SupportedLanguages,\r
428 &WinNtBusDevice->ControllerNameTable,\r
429 L"Windows Bus Controller",\r
430 FALSE\r
431 );\r
432\r
433\r
434 Status = gBS->InstallMultipleProtocolInterfaces (\r
435 &ControllerHandle,\r
436 &gWinNtBusDriverGuid,\r
437 WinNtBusDevice,\r
438 NULL\r
439 );\r
440 if (EFI_ERROR (Status)) {\r
441 FreeUnicodeStringTable (WinNtBusDevice->ControllerNameTable);\r
442 FreePool (WinNtBusDevice);\r
443 return Status;\r
444 }\r
445 }\r
446\r
447 //\r
448 // Loop on the Variable list. Parse each variable to produce a set of handles that\r
449 // represent virtual hardware devices.\r
450 //\r
451 for (Index = 0; Index < NT_PCD_ARRAY_SIZE; Index++) {\r
452 PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token);\r
453 ASSERT (PcdTempStr != NULL);\r
454\r
455 TempStrSize = StrLen (PcdTempStr);\r
456 TempStr = AllocateMemory ((TempStrSize * sizeof (CHAR16)) + 1);\r
457 StrCpy (TempStr, PcdTempStr);\r
458\r
459 StartString = TempStr;\r
460\r
461 //\r
462 // Parse the envirnment variable into sub strings using '!' as a delimator.\r
463 // Each substring needs it's own handle to be added to the system. This code\r
464 // does not understand the sub string. Thats the device drivers job.\r
465 //\r
466 Count = 0;\r
467 while (*StartString != '\0') {\r
468\r
469 //\r
470 // Find the end of the sub string\r
471 //\r
472 SubString = StartString;\r
473 while (*SubString != '\0' && *SubString != '!') {\r
474 SubString++;\r
475 }\r
476\r
477 if (*SubString == '!') {\r
478 //\r
479 // Replace token with '\0' to make sub strings. If this is the end\r
480 // of the string SubString will already point to NULL.\r
481 //\r
482 *SubString = '\0';\r
483 SubString++;\r
484 }\r
485\r
486 CreateDevice = TRUE;\r
487 if (RemainingDevicePath != NULL) {\r
488 CreateDevice = FALSE;\r
489 //\r
490 // Check if RemainingDevicePath is the End of Device Path Node, \r
491 // if yes, don't create any child device \r
492 //\r
493 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
494 //\r
495 // If RemainingDevicePath isn't the End of Device Path Node,\r
496 // check its validation\r
497 //\r
498 Node = (WIN_NT_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;\r
499 if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&\r
500 Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&\r
501 DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)\r
502 ) {\r
503 if (CompareGuid (&Node->VendorDevicePath.Guid, mPcdEnvironment[Index].DevicePathGuid) &&\r
504 Node->Instance == Count\r
505 ) {\r
506 CreateDevice = TRUE;\r
507 }\r
508 }\r
509 }\r
510 }\r
511\r
512 if (CreateDevice) {\r
513\r
514 //\r
515 // Allocate instance structure, and fill in parent information.\r
516 //\r
517 WinNtDevice = AllocateMemory (sizeof (WIN_NT_IO_DEVICE));\r
518 if (WinNtDevice == NULL) {\r
519 return EFI_OUT_OF_RESOURCES;\r
520 }\r
521\r
522 WinNtDevice->Handle = NULL;\r
523 WinNtDevice->ControllerHandle = ControllerHandle;\r
524 WinNtDevice->ParentDevicePath = ParentDevicePath;\r
525\r
526 WinNtDevice->WinNtIo.WinNtThunk = WinNtThunk;\r
527\r
528 //\r
529 // Plus 2 to account for the NULL at the end of the Unicode string\r
530 //\r
531 StringSize = (UINTN) ((UINT8 *) SubString - (UINT8 *) StartString) + sizeof (CHAR16);\r
532 WinNtDevice->WinNtIo.EnvString = AllocateMemory (StringSize);\r
533 if (WinNtDevice->WinNtIo.EnvString != NULL) {\r
534 CopyMem (WinNtDevice->WinNtIo.EnvString, StartString, StringSize);\r
535 }\r
536\r
537 WinNtDevice->ControllerNameTable = NULL;\r
538\r
539 WinNtThunk->SPrintf (ComponentName, sizeof (ComponentName), L"%s", WinNtDevice->WinNtIo.EnvString);\r
540\r
541 WinNtDevice->DevicePath = WinNtBusCreateDevicePath (\r
542 ParentDevicePath,\r
543 mPcdEnvironment[Index].DevicePathGuid,\r
544 Count\r
545 );\r
546 if (WinNtDevice->DevicePath == NULL) {\r
547 FreePool (WinNtDevice);\r
548 return EFI_OUT_OF_RESOURCES;\r
549 }\r
550\r
551 AddUnicodeString2 (\r
552 "eng",\r
553 gWinNtBusDriverComponentName.SupportedLanguages,\r
554 &WinNtDevice->ControllerNameTable,\r
555 ComponentName,\r
556 TRUE\r
557 );\r
558 AddUnicodeString2 (\r
559 "en",\r
560 gWinNtBusDriverComponentName2.SupportedLanguages,\r
561 &WinNtDevice->ControllerNameTable,\r
562 ComponentName,\r
563 FALSE\r
564 );\r
565\r
566\r
567 WinNtDevice->WinNtIo.TypeGuid = mPcdEnvironment[Index].DevicePathGuid;\r
568 WinNtDevice->WinNtIo.InstanceNumber = Count;\r
569\r
570 WinNtDevice->Signature = WIN_NT_IO_DEVICE_SIGNATURE;\r
571\r
572 Status = gBS->InstallMultipleProtocolInterfaces (\r
573 &WinNtDevice->Handle,\r
574 &gEfiDevicePathProtocolGuid,\r
575 WinNtDevice->DevicePath,\r
576 &gEfiWinNtIoProtocolGuid,\r
577 &WinNtDevice->WinNtIo,\r
578 NULL\r
579 );\r
580 if (EFI_ERROR (Status)) {\r
581 FreeUnicodeStringTable (WinNtDevice->ControllerNameTable);\r
582 FreePool (WinNtDevice);\r
583 } else {\r
584 //\r
585 // Open For Child Device\r
586 //\r
587 Status = gBS->OpenProtocol (\r
588 ControllerHandle,\r
589 &gEfiWinNtThunkProtocolGuid,\r
590 (VOID **) &WinNtThunk,\r
591 This->DriverBindingHandle,\r
592 WinNtDevice->Handle,\r
593 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
594 );\r
595 }\r
596 }\r
597\r
598 //\r
599 // Parse Next sub string. This will point to '\0' if we are at the end.\r
600 //\r
601 Count++;\r
602 StartString = SubString;\r
603 }\r
604\r
605 FreePool (TempStr);\r
606 }\r
607\r
608 return EFI_SUCCESS;\r
609}\r
610\r
611\r
612EFI_STATUS\r
613EFIAPI\r
614WinNtBusDriverBindingStop (\r
615 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
616 IN EFI_HANDLE ControllerHandle,\r
617 IN UINTN NumberOfChildren,\r
618 IN EFI_HANDLE *ChildHandleBuffer\r
619 )\r
620/*++\r
621\r
622Routine Description:\r
623\r
624Arguments:\r
625\r
626Returns:\r
627\r
628 None\r
629\r
630--*/\r
631// TODO: This - add argument and description to function comment\r
632// TODO: ControllerHandle - add argument and description to function comment\r
633// TODO: NumberOfChildren - add argument and description to function comment\r
634// TODO: ChildHandleBuffer - add argument and description to function comment\r
635// TODO: EFI_SUCCESS - add return value to function comment\r
636// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
637// TODO: EFI_SUCCESS - add return value to function comment\r
638{\r
639 EFI_STATUS Status;\r
640 UINTN Index;\r
641 BOOLEAN AllChildrenStopped;\r
642 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
643 WIN_NT_BUS_DEVICE *WinNtBusDevice;\r
644 WIN_NT_IO_DEVICE *WinNtDevice;\r
645 EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk;\r
646\r
647 //\r
648 // Complete all outstanding transactions to Controller.\r
649 // Don't allow any new transaction to Controller to be started.\r
650 //\r
651\r
652 if (NumberOfChildren == 0) {\r
653 //\r
654 // Close the bus driver\r
655 //\r
656 Status = gBS->OpenProtocol (\r
657 ControllerHandle,\r
658 &gWinNtBusDriverGuid,\r
659 (VOID **) &WinNtBusDevice,\r
660 This->DriverBindingHandle,\r
661 ControllerHandle,\r
662 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
663 );\r
664 if (EFI_ERROR (Status)) {\r
665 return Status;\r
666 }\r
667\r
668 gBS->UninstallMultipleProtocolInterfaces (\r
669 ControllerHandle,\r
670 &gWinNtBusDriverGuid,\r
671 WinNtBusDevice,\r
672 NULL\r
673 );\r
674\r
675 FreeUnicodeStringTable (WinNtBusDevice->ControllerNameTable);\r
676\r
677 FreePool (WinNtBusDevice);\r
678\r
679 gBS->CloseProtocol (\r
680 ControllerHandle,\r
681 &gEfiWinNtThunkProtocolGuid,\r
682 This->DriverBindingHandle,\r
683 ControllerHandle\r
684 );\r
685\r
686 gBS->CloseProtocol (\r
687 ControllerHandle,\r
688 &gEfiDevicePathProtocolGuid,\r
689 This->DriverBindingHandle,\r
690 ControllerHandle\r
691 );\r
692 return EFI_SUCCESS;\r
693 }\r
694\r
695 AllChildrenStopped = TRUE;\r
696\r
697 for (Index = 0; Index < NumberOfChildren; Index++) {\r
698\r
699 Status = gBS->OpenProtocol (\r
700 ChildHandleBuffer[Index],\r
701 &gEfiWinNtIoProtocolGuid,\r
702 (VOID **) &WinNtIo,\r
703 This->DriverBindingHandle,\r
704 ControllerHandle,\r
705 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
706 );\r
707 if (!EFI_ERROR (Status)) {\r
708\r
709 WinNtDevice = WIN_NT_IO_DEVICE_FROM_THIS (WinNtIo);\r
710\r
711 Status = gBS->CloseProtocol (\r
712 ControllerHandle,\r
713 &gEfiWinNtThunkProtocolGuid,\r
714 This->DriverBindingHandle,\r
715 WinNtDevice->Handle\r
716 );\r
717\r
718 Status = gBS->UninstallMultipleProtocolInterfaces (\r
719 WinNtDevice->Handle,\r
720 &gEfiDevicePathProtocolGuid,\r
721 WinNtDevice->DevicePath,\r
722 &gEfiWinNtIoProtocolGuid,\r
723 &WinNtDevice->WinNtIo,\r
724 NULL\r
725 );\r
726\r
727 if (EFI_ERROR (Status)) {\r
728 gBS->OpenProtocol (\r
729 ControllerHandle,\r
730 &gEfiWinNtThunkProtocolGuid,\r
731 (VOID **) &WinNtThunk,\r
732 This->DriverBindingHandle,\r
733 WinNtDevice->Handle,\r
734 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
735 );\r
736 } else {\r
737 //\r
738 // Close the child handle\r
739 //\r
740 FreeUnicodeStringTable (WinNtDevice->ControllerNameTable);\r
741 FreePool (WinNtDevice);\r
742 }\r
743 }\r
744\r
745 if (EFI_ERROR (Status)) {\r
746 AllChildrenStopped = FALSE;\r
747 }\r
748 }\r
749\r
750 if (!AllChildrenStopped) {\r
751 return EFI_DEVICE_ERROR;\r
752 }\r
753\r
754 return EFI_SUCCESS;\r
755}\r
756\r
757EFI_DEVICE_PATH_PROTOCOL *\r
758WinNtBusCreateDevicePath (\r
759 IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath,\r
760 IN EFI_GUID *Guid,\r
761 IN UINT16 InstanceNumber\r
762 )\r
763/*++\r
764\r
765Routine Description:\r
766 Create a device path node using Guid and InstanceNumber and append it to\r
767 the passed in RootDevicePath\r
768\r
769Arguments:\r
770 RootDevicePath - Root of the device path to return.\r
771\r
772 Guid - GUID to use in vendor device path node.\r
773\r
774 InstanceNumber - Instance number to use in the vendor device path. This\r
775 argument is needed to make sure each device path is unique.\r
776\r
777Returns:\r
778\r
779 EFI_DEVICE_PATH_PROTOCOL\r
780\r
781--*/\r
782{\r
783 WIN_NT_VENDOR_DEVICE_PATH_NODE DevicePath;\r
784\r
785 DevicePath.VendorDevicePath.Header.Type = HARDWARE_DEVICE_PATH;\r
786 DevicePath.VendorDevicePath.Header.SubType = HW_VENDOR_DP;\r
787 SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE));\r
788\r
789 //\r
790 // The GUID defines the Class\r
791 //\r
792 CopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID));\r
793\r
794 //\r
795 // Add an instance number so we can make sure there are no Device Path\r
796 // duplication.\r
797 //\r
798 DevicePath.Instance = InstanceNumber;\r
799\r
800 return AppendDevicePathNode (\r
801 RootDevicePath,\r
802 (EFI_DEVICE_PATH_PROTOCOL *) &DevicePath\r
803 );\r
804}\r