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