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