summaryrefslogtreecommitdiffstats
path: root/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c
blob: 3bf5beba7d4a46c7d5b0706b5871b1f732c9c592 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/** @file

  The boot services environment configuration library for the Context Buffer Sample PRM module.

  Copyright (c) Microsoft Corporation
  SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/PrmConfig.h>
#include <Samples/PrmSampleContextBufferModule/Include/StaticData.h>

#include <PrmContextBuffer.h>
#include <PrmDataBuffer.h>

STATIC EFI_HANDLE  mPrmConfigProtocolHandle;

// {5a6cf42b-8bb4-472c-a233-5c4dc4033dc7}
STATIC CONST EFI_GUID mPrmModuleGuid = {0x5a6cf42b, 0x8bb4, 0x472c, {0xa2, 0x33, 0x5c, 0x4d, 0xc4, 0x03, 0x3d, 0xc7}};

// {e1466081-7562-430f-896b-b0e523dc335a}
STATIC CONST EFI_GUID mDumpStaticDataBufferPrmHandlerGuid = {0xe1466081, 0x7562, 0x430f, {0x89, 0x6b, 0xb0, 0xe5, 0x23, 0xdc, 0x33, 0x5a}};

/**
  Populates the static data buffer for this PRM module.

  @param[out] StaticDataBuffer  A pointer to the static data buffer.

  @retval EFI_SUCCESS           The static data buffer was populated successfully.
  @retval EFI_INVALID_PARAMETER The StaticDataBuffer pointer argument is NULL.

**/
EFI_STATUS
PopulateStaticDataBuffer (
  OUT STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE  *StaticDataBuffer
  )
{
  if (StaticDataBuffer == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Note: In a real-world module these values would likely come from somewhere
  // like a Setup menu option, PCD, binary data, runtime device info, etc. Ideally,
  // this configuration library would be provided an API to get what it needs (the data)
  // and not be concerned with how the data is provided. This makes the PRM module more
  // portable across systems.
  //
  StaticDataBuffer->Policy1Enabled = TRUE;
  StaticDataBuffer->Policy2Enabled = FALSE;
  SetMem (StaticDataBuffer->SomeValueArray, ARRAY_SIZE (StaticDataBuffer->SomeValueArray), 'D');

  return EFI_SUCCESS;
}

/**
  Allocates and populates the static data buffer for this PRM module.

  @param[out] StaticDataBuffer  A pointer to a pointer to the static data buffer.

  @retval EFI_SUCCESS           The static data buffer was allocated and filled successfully.
  @retval EFI_INVALID_PARAMETER The StaticDataBuffer pointer argument is NULL.
  @retval EFI_OUT_OF_RESOURCES  Insufficient memory resources to allocate the static data buffer.

**/
EFI_STATUS
GetStaticDataBuffer (
  OUT PRM_DATA_BUFFER         **StaticDataBuffer
  )
{
  EFI_STATUS                  Status;
  PRM_DATA_BUFFER             *DataBuffer;
  UINTN                       DataBufferLength;

  if (StaticDataBuffer == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  *StaticDataBuffer = NULL;

  //
  // Length of the data buffer = Buffer Header Size + Buffer Data Size
  //
  DataBufferLength = sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE);

  DataBuffer = AllocateRuntimeZeroPool (DataBufferLength);
  if (DataBuffer == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Initialize the data buffer header
  //
  DataBuffer->Header.Signature = PRM_DATA_BUFFER_HEADER_SIGNATURE;
  DataBuffer->Header.Length = (UINT32) DataBufferLength;

  Status = PopulateStaticDataBuffer ((STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE *) &DataBuffer->Data[0]);
  ASSERT_EFI_ERROR (Status);

  *StaticDataBuffer = DataBuffer;
  return EFI_SUCCESS;
}

/**
  Constructor of the PRM configuration library.

  @param[in] ImageHandle        The image handle of the driver.
  @param[in] SystemTable        The EFI System Table pointer.

  @retval EFI_SUCCESS           The shell command handlers were installed successfully.
  @retval EFI_UNSUPPORTED       The shell level required was not found.
**/
EFI_STATUS
EFIAPI
ContextBufferModuleConfigLibConstructor (
  IN  EFI_HANDLE              ImageHandle,
  IN  EFI_SYSTEM_TABLE        *SystemTable
  )
{
  EFI_STATUS                  Status;
  PRM_CONTEXT_BUFFER          *PrmContextBuffer;
  PRM_DATA_BUFFER             *StaticDataBuffer;
  PRM_CONFIG_PROTOCOL         *PrmConfigProtocol;

  PrmContextBuffer = NULL;
  StaticDataBuffer = NULL;
  PrmConfigProtocol = NULL;

  /*
    In this sample PRM module, the protocol describing this sample module's resources is simply
    installed in the constructor.

    However, if some data is not available until later, this constructor could register a callback
    on the dependency for the data to be available (e.g. ability to communicate with some device)
    and then install the protocol. The requirement is that the protocol is installed before end of DXE.
  */

  //
  // Allocate and populate the static data buffer
  //
  Status = GetStaticDataBuffer (&StaticDataBuffer);
  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status) || StaticDataBuffer == NULL) {
    goto Done;
  }

  //
  // Allocate and populate the context buffer
  //
  // This sample module uses a single context buffer for all the handlers
  // Todo: This can be done more elegantly in the future. Likely though a library service.
  //
  PrmContextBuffer = AllocateRuntimeZeroPool (sizeof (*PrmContextBuffer));
  ASSERT (PrmContextBuffer != NULL);
  if (PrmContextBuffer == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Done;
  }
  CopyGuid (&PrmContextBuffer->HandlerGuid, &mDumpStaticDataBufferPrmHandlerGuid);
  PrmContextBuffer->Signature = PRM_CONTEXT_BUFFER_SIGNATURE;
  PrmContextBuffer->Version = PRM_CONTEXT_BUFFER_INTERFACE_VERSION;
  PrmContextBuffer->StaticDataBuffer = StaticDataBuffer;

  PrmConfigProtocol = AllocateZeroPool (sizeof (*PrmConfigProtocol));
  ASSERT (PrmConfigProtocol != NULL);
  if (PrmConfigProtocol == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Done;
  }
  CopyGuid (&PrmConfigProtocol->ModuleContextBuffers.ModuleGuid, &mPrmModuleGuid);
  PrmConfigProtocol->ModuleContextBuffers.BufferCount = 1;
  PrmConfigProtocol->ModuleContextBuffers.Buffer = PrmContextBuffer;

  //
  // Install the PRM Configuration Protocol for this module. This indicates the configuration
  // library has completed resource initialization for the PRM module.
  //
  Status = gBS->InstallProtocolInterface (
                  &mPrmConfigProtocolHandle,
                  &gPrmConfigProtocolGuid,
                  EFI_NATIVE_INTERFACE,
                  (VOID *) PrmConfigProtocol
                  );

Done:
  if (EFI_ERROR (Status)) {
    if (StaticDataBuffer != NULL) {
      FreePool (StaticDataBuffer);
    }
    if (PrmContextBuffer != NULL) {
      FreePool (PrmContextBuffer);
    }
    if (PrmConfigProtocol != NULL) {
      FreePool (PrmConfigProtocol);
    }
  }

  return Status;
}