Update video card preference policy, together with some memory leaks in Generic BDS...
[people/mcb30/edk2.git] / edk2 / EdkUnixPkg / Library / EdkGenericBdsLib / BdsConsole.c
1 /*++\r
2 \r
3 Copyright (c) 2006, 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   BdsConsole.c\r
15 \r
16 Abstract:\r
17 \r
18   BDS Lib functions which contain all the code to connect console device\r
19 \r
20 --*/\r
21 \r
22 BOOLEAN\r
23 IsNvNeed (\r
24   IN CHAR16 *ConVarName\r
25   )\r
26 {\r
27   CHAR16 *Ptr;\r
28   \r
29   Ptr = ConVarName;\r
30   \r
31   //\r
32   // If the variable includes "Dev" at last, we consider\r
33   // it does not support NV attribute.\r
34   //\r
35   while (*Ptr) {\r
36     Ptr++;\r
37   }\r
38   \r
39   if ((*(Ptr - 3) == 'D') && (*(Ptr - 2) == 'e') && (*(Ptr - 1) == 'v')) {\r
40     return FALSE;\r
41   } else {\r
42     return TRUE;\r
43   }\r
44 }\r
45 \r
46 EFI_STATUS\r
47 BdsLibUpdateConsoleVariable (\r
48   IN  CHAR16                    *ConVarName,\r
49   IN  EFI_DEVICE_PATH_PROTOCOL  *CustomizedConDevicePath,\r
50   IN  EFI_DEVICE_PATH_PROTOCOL  *ExclusiveDevicePath\r
51   )\r
52 /*++\r
53 \r
54 Routine Description:\r
55 \r
56   This function update console variable based on ConVarName, it can \r
57   add or remove one specific console device path from the variable\r
58 \r
59 Arguments:\r
60 \r
61   ConVarName   - Console related variable name, ConIn, ConOut, ErrOut.\r
62 \r
63   CustomizedConDevicePath - The console device path which will be added to\r
64                             the console variable ConVarName, this parameter\r
65                             can not be multi-instance.\r
66 \r
67   ExclusiveDevicePath     - The console device path which will be removed\r
68                             from the console variable ConVarName, this\r
69                             parameter can not be multi-instance.\r
70 \r
71 Returns:\r
72 \r
73   EFI_UNSUPPORTED         - Add or remove the same device path.\r
74   \r
75   EFI_SUCCESS             - Success add or remove the device path from \r
76                             the console variable.\r
77 \r
78 --*/\r
79 {\r
80   EFI_STATUS                Status;\r
81   EFI_DEVICE_PATH_PROTOCOL  *VarConsole;\r
82   UINTN                     DevicePathSize;\r
83   EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;\r
84   EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;\r
85   UINT32                    Attributes;\r
86 \r
87   VarConsole      = NULL;\r
88   DevicePathSize  = 0;\r
89   Status          = EFI_UNSUPPORTED;\r
90 \r
91   //\r
92   // Notes: check the device path point, here should check\r
93   // with compare memory\r
94   //\r
95   if (CustomizedConDevicePath == ExclusiveDevicePath) {\r
96     return EFI_UNSUPPORTED;\r
97   }\r
98   //\r
99   // Delete the ExclusiveDevicePath from current default console\r
100   //\r
101   VarConsole = BdsLibGetVariableAndSize (\r
102                 ConVarName,\r
103                 &gEfiGlobalVariableGuid,\r
104                 &DevicePathSize\r
105                 );\r
106                 \r
107   //\r
108   // Initialize NewDevicePath\r
109   //\r
110   NewDevicePath  = VarConsole;\r
111   \r
112   //\r
113   // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.\r
114   // In the end, NewDevicePath is the final device path.\r
115   //\r
116   if (ExclusiveDevicePath != NULL && VarConsole != NULL) {\r
117       NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath);\r
118   }\r
119   //\r
120   // Try to append customized device path to NewDevicePath.\r
121   //\r
122   if (CustomizedConDevicePath != NULL) {\r
123     if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {\r
124       //\r
125       // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.\r
126       //\r
127       NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);\r
128       //\r
129       // In the first check, the default console variable will be null,\r
130       // just append current customized device path\r
131       //\r
132       TempNewDevicePath = NewDevicePath;\r
133       NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);\r
134       BdsLibSafeFreePool(TempNewDevicePath);\r
135     }\r
136   }\r
137   \r
138   //\r
139   // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.\r
140   //\r
141   if (IsNvNeed(ConVarName)) {\r
142     //\r
143     // ConVarName has NV attribute.\r
144     //\r
145     Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
146   } else {\r
147     //\r
148     // ConVarName does not have NV attribute.\r
149     //\r
150     Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
151   }\r
152   \r
153   //\r
154   // Finally, Update the variable of the default console by NewDevicePath\r
155   //\r
156   gRT->SetVariable (\r
157         ConVarName,\r
158         &gEfiGlobalVariableGuid,\r
159         Attributes,\r
160         GetDevicePathSize (NewDevicePath),\r
161         NewDevicePath\r
162         );\r
163 \r
164   if (VarConsole == NewDevicePath) {\r
165     BdsLibSafeFreePool(VarConsole);\r
166   } else {\r
167     BdsLibSafeFreePool(VarConsole);\r
168     BdsLibSafeFreePool(NewDevicePath);\r
169   }\r
170 \r
171   return EFI_SUCCESS;\r
172 \r
173 }\r
174 \r
175 EFI_STATUS\r
176 BdsLibConnectConsoleVariable (\r
177   IN  CHAR16                 *ConVarName\r
178   )\r
179 /*++\r
180 \r
181 Routine Description:\r
182 \r
183   Connect the console device base on the variable ConVarName, if\r
184   device path of the ConVarName is multi-instance device path, if\r
185   anyone of the instances is connected success, then this function\r
186   will return success.\r
187 \r
188 Arguments:\r
189 \r
190   ConVarName   - Console related variable name, ConIn, ConOut, ErrOut.\r
191 \r
192 Returns:\r
193 \r
194   EFI_NOT_FOUND           - There is not any console devices connected success\r
195   \r
196   EFI_SUCCESS             - Success connect any one instance of the console\r
197                             device path base on the variable ConVarName.\r
198 \r
199 --*/\r
200 {\r
201   EFI_STATUS                Status;\r
202   EFI_DEVICE_PATH_PROTOCOL  *StartDevicePath;\r
203   UINTN                     VariableSize;\r
204   EFI_DEVICE_PATH_PROTOCOL  *Instance;\r
205   EFI_DEVICE_PATH_PROTOCOL  *Next;\r
206   EFI_DEVICE_PATH_PROTOCOL  *CopyOfDevicePath;\r
207   UINTN                     Size;\r
208   BOOLEAN                   DeviceExist;\r
209 \r
210   Status      = EFI_SUCCESS;\r
211   DeviceExist = FALSE;\r
212 \r
213   //\r
214   // Check if the console variable exist\r
215   //\r
216   StartDevicePath = BdsLibGetVariableAndSize (\r
217                       ConVarName,\r
218                       &gEfiGlobalVariableGuid,\r
219                       &VariableSize\r
220                       );\r
221   if (StartDevicePath == NULL) {\r
222     return EFI_UNSUPPORTED;\r
223   }\r
224 \r
225   CopyOfDevicePath = StartDevicePath;\r
226   do {\r
227     //\r
228     // Check every instance of the console variable\r
229     //\r
230     Instance  = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);\r
231     Next      = Instance;\r
232     while (!IsDevicePathEndType (Next)) {\r
233       Next = NextDevicePathNode (Next);\r
234     }\r
235 \r
236     SetDevicePathEndNode (Next);\r
237 \r
238     //\r
239     // Connect the instance device path\r
240     //\r
241     Status = BdsLibConnectDevicePath (Instance);\r
242     if (EFI_ERROR (Status)) {\r
243       //\r
244       // Delete the instance from the console varialbe\r
245       //\r
246       BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance);\r
247     } else {\r
248       DeviceExist = TRUE;\r
249     }\r
250     BdsLibSafeFreePool(Instance);\r
251   } while (CopyOfDevicePath != NULL);\r
252 \r
253   gBS->FreePool (StartDevicePath);\r
254 \r
255   if (DeviceExist == FALSE) {\r
256     return EFI_NOT_FOUND;\r
257   }\r
258 \r
259   return EFI_SUCCESS;\r
260 }\r
261 \r
262 VOID\r
263 BdsLibConnectAllConsoles (\r
264   VOID\r
265   )\r
266 /*++\r
267 \r
268 Routine Description:\r
269 \r
270   This function will search every simpletxt devive in current system,\r
271   and make every simpletxt device as pertantial console device.\r
272 \r
273 Arguments:\r
274 \r
275   None\r
276 \r
277 Returns:\r
278 \r
279   None\r
280 \r
281 --*/\r
282 {\r
283   EFI_STATUS                Status;\r
284   UINTN                     Index;\r
285   EFI_DEVICE_PATH_PROTOCOL  *ConDevicePath;\r
286   UINTN                     HandleCount;\r
287   EFI_HANDLE                *HandleBuffer;\r
288 \r
289   Index         = 0;\r
290   HandleCount   = 0;\r
291   HandleBuffer  = NULL;\r
292   ConDevicePath = NULL;\r
293 \r
294   //\r
295   // Update all the console varables\r
296   //\r
297   Status = gBS->LocateHandleBuffer (\r
298                   ByProtocol,\r
299                   &gEfiSimpleTextInProtocolGuid,\r
300                   NULL,\r
301                   &HandleCount,\r
302                   &HandleBuffer\r
303                   );\r
304   for (Index = 0; Index < HandleCount; Index++) {\r
305     Status = gBS->HandleProtocol (\r
306                     HandleBuffer[Index],\r
307                     &gEfiDevicePathProtocolGuid,\r
308                     (VOID **) &ConDevicePath\r
309                     );\r
310     BdsLibUpdateConsoleVariable (L"ConIn", ConDevicePath, NULL);\r
311   }\r
312 \r
313   BdsLibSafeFreePool(HandleBuffer);\r
314 \r
315   Status = gBS->LocateHandleBuffer (\r
316                   ByProtocol,\r
317                   &gEfiSimpleTextOutProtocolGuid,\r
318                   NULL,\r
319                   &HandleCount,\r
320                   &HandleBuffer\r
321                   );\r
322   for (Index = 0; Index < HandleCount; Index++) {\r
323     Status = gBS->HandleProtocol (\r
324                     HandleBuffer[Index],\r
325                     &gEfiDevicePathProtocolGuid,\r
326                     (VOID **) &ConDevicePath\r
327                     );\r
328     BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL);\r
329     BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL);\r
330   }\r
331 \r
332   BdsLibSafeFreePool(HandleBuffer);\r
333 \r
334   //\r
335   // Connect all console variables\r
336   //\r
337   BdsLibConnectAllDefaultConsoles ();\r
338 \r
339 }\r
340 \r
341 EFI_STATUS\r
342 BdsLibConnectAllDefaultConsoles (\r
343   VOID\r
344   )\r
345 /*++\r
346 \r
347 Routine Description:\r
348 \r
349   This function will connect console device base on the console \r
350   device variable ConIn, ConOut and ErrOut.\r
351 \r
352 Arguments:\r
353 \r
354   None\r
355 \r
356 Returns:\r
357 \r
358   EFI_SUCCESS      - At least one of the ConIn and ConOut device have\r
359                      been connected success.\r
360                      \r
361   EFI_STATUS       - Return the status of BdsLibConnectConsoleVariable ().\r
362 \r
363 --*/\r
364 {\r
365   EFI_STATUS                Status;\r
366 \r
367   //\r
368   // Connect all default console variables\r
369   //\r
370   Status = BdsLibConnectConsoleVariable (L"ConIn");\r
371   if (EFI_ERROR (Status)) {\r
372     return Status;\r
373   }\r
374 \r
375   Status = BdsLibConnectConsoleVariable (L"ConOut");\r
376   if (EFI_ERROR (Status)) {\r
377     return Status;\r
378   }\r
379   //\r
380   // Special treat the err out device, becaues the null\r
381   // err out var is legal.\r
382   //\r
383   BdsLibConnectConsoleVariable (L"ErrOut");\r
384 \r
385   return EFI_SUCCESS;\r
386 \r
387 }\r