1/** @file
2*
3*  Copyright (c) 2011-2015, ARM Limited. All rights reserved.
4*
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**/
14
15#include "BdsInternal.h"
16
17EFI_STATUS
18ShutdownUefiBootServices (
19  VOID
20  )
21{
22  EFI_STATUS              Status;
23  UINTN                   MemoryMapSize;
24  EFI_MEMORY_DESCRIPTOR   *MemoryMap;
25  UINTN                   MapKey;
26  UINTN                   DescriptorSize;
27  UINT32                  DescriptorVersion;
28  UINTN                   Pages;
29
30  MemoryMap = NULL;
31  MemoryMapSize = 0;
32  Pages = 0;
33
34  do {
35    Status = gBS->GetMemoryMap (
36                    &MemoryMapSize,
37                    MemoryMap,
38                    &MapKey,
39                    &DescriptorSize,
40                    &DescriptorVersion
41                    );
42    if (Status == EFI_BUFFER_TOO_SMALL) {
43
44      Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;
45      MemoryMap = AllocatePages (Pages);
46
47      //
48      // Get System MemoryMap
49      //
50      Status = gBS->GetMemoryMap (
51                      &MemoryMapSize,
52                      MemoryMap,
53                      &MapKey,
54                      &DescriptorSize,
55                      &DescriptorVersion
56                      );
57    }
58
59    // Don't do anything between the GetMemoryMap() and ExitBootServices()
60    if (!EFI_ERROR(Status)) {
61      Status = gBS->ExitBootServices (gImageHandle, MapKey);
62      if (EFI_ERROR(Status)) {
63        FreePages (MemoryMap, Pages);
64        MemoryMap = NULL;
65        MemoryMapSize = 0;
66      }
67    }
68  } while (EFI_ERROR(Status));
69
70  return Status;
71}
72
73/**
74  Connect all DXE drivers
75
76  @retval EFI_SUCCESS           All drivers have been connected
77  @retval EFI_NOT_FOUND         No handles match the search.
78  @retval EFI_OUT_OF_RESOURCES  There is not resource pool memory to store the matching results.
79
80**/
81EFI_STATUS
82BdsConnectAllDrivers (
83  VOID
84  )
85{
86  UINTN                     HandleCount, Index;
87  EFI_HANDLE                *HandleBuffer;
88  EFI_STATUS                Status;
89
90  do {
91    // Locate all the driver handles
92    Status = gBS->LocateHandleBuffer (
93                AllHandles,
94                NULL,
95                NULL,
96                &HandleCount,
97                &HandleBuffer
98                );
99    if (EFI_ERROR (Status)) {
100      break;
101    }
102
103    // Connect every handles
104    for (Index = 0; Index < HandleCount; Index++) {
105      gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
106    }
107
108    if (HandleBuffer != NULL) {
109      FreePool (HandleBuffer);
110    }
111
112    // Check if new handles have been created after the start of the previous handles
113    Status = gDS->Dispatch ();
114  } while (!EFI_ERROR(Status));
115
116  return EFI_SUCCESS;
117}
118
119EFI_STATUS
120GetGlobalEnvironmentVariable (
121  IN     CONST CHAR16*   VariableName,
122  IN     VOID*           DefaultValue,
123  IN OUT UINTN*          Size,
124  OUT    VOID**          Value
125  )
126{
127  return GetEnvironmentVariable (VariableName, &gEfiGlobalVariableGuid,
128           DefaultValue, Size, Value);
129}
130
131EFI_STATUS
132GetEnvironmentVariable (
133  IN     CONST CHAR16*   VariableName,
134  IN     EFI_GUID*       VendorGuid,
135  IN     VOID*           DefaultValue,
136  IN OUT UINTN*          Size,
137  OUT    VOID**          Value
138  )
139{
140  EFI_STATUS  Status;
141  UINTN       VariableSize;
142
143  // Try to get the variable size.
144  *Value = NULL;
145  VariableSize = 0;
146  Status = gRT->GetVariable ((CHAR16 *) VariableName, VendorGuid, NULL, &VariableSize, *Value);
147  if (Status == EFI_NOT_FOUND) {
148    if ((DefaultValue != NULL) && (Size != NULL) && (*Size != 0)) {
149      // If the environment variable does not exist yet then set it with the default value
150      Status = gRT->SetVariable (
151                    (CHAR16*)VariableName,
152                    VendorGuid,
153                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
154                    *Size,
155                    DefaultValue
156                    );
157      *Value = AllocateCopyPool (*Size, DefaultValue);
158    } else {
159      return EFI_NOT_FOUND;
160    }
161  } else if (Status == EFI_BUFFER_TOO_SMALL) {
162    // Get the environment variable value
163    *Value = AllocatePool (VariableSize);
164    if (*Value == NULL) {
165      return EFI_OUT_OF_RESOURCES;
166    }
167
168    Status = gRT->GetVariable ((CHAR16 *)VariableName, VendorGuid, NULL, &VariableSize, *Value);
169    if (EFI_ERROR (Status)) {
170      FreePool(*Value);
171      return EFI_INVALID_PARAMETER;
172    }
173
174    if (Size) {
175      *Size = VariableSize;
176    }
177  } else {
178    *Value = AllocateCopyPool (*Size, DefaultValue);
179    return Status;
180  }
181
182  return EFI_SUCCESS;
183}
184