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