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