microsoft/mu_feature_ffa

Public

mirrored from https://github.com/microsoft/mu_feature_ffaAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
858d1559f5d2e1e97ccf62290e96060595aa2dfb

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

FfaFeaturePkg/Library/NotificationServiceLib/NotificationServiceLib.c

543lines · modecode

1/** @file
2 Implementation for the Notification Service
3
4 Copyright (c), Microsoft Corporation.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include <Uefi.h>
10#include <Library/DebugLib.h>
11#include <Library/BaseMemoryLib.h>
12#include <Library/NotificationServiceLib.h>
13#include <Guid/NotificationServiceFfa.h>
14
15/* Notification Service Defines */
16#define NOTIFICATION_MAX_SERVICES (16)
17#define NOTIFICATION_MAX_IDS (64)
18#define NOTIFICATION_ID_NOT_FOUND (-1)
19
20/* Notification Service Structures */
21typedef struct {
22 UINT32 BitNum; // The OS translation bitmap value
23 UINT32 IdNum; // The logical ID for the service
24 BOOLEAN InUse;
25} NotifBits;
26
27typedef struct {
28 UINT8 ServiceUuid[16];
29 NotifBits ServiceBits[NOTIFICATION_MAX_IDS];
30 BOOLEAN InUse;
31} NotifService;
32
33/* Notification Service Variables */
34STATIC BOOLEAN IdsAcquired = FALSE;
35STATIC UINT16 SourceId = 0;
36STATIC UINT16 DestinationId = 0;
37STATIC UINT64 GlobalBitmask = 0;
38STATIC NotifService NotificationServices[NOTIFICATION_MAX_SERVICES] = { 0 };
39
40/**
41 Checks if the ID passed in matches one stored within the service structure
42
43 @param IdNum The ID number to look for
44 @param Service The service to search for the given ID
45
46 @return The index of the ID if found, otherwise -1 (NOTIFICATION_ID_NOT_FOUND)
47
48**/
49STATIC
50INT8
51IsMatchingId (
52 UINT32 IdNum,
53 NotifService *Service
54 )
55{
56 UINT8 Index;
57
58 /* Validate the incoming function parameters */
59 if (Service == NULL) {
60 return NOTIFICATION_ID_NOT_FOUND;
61 }
62
63 for (Index = 0; Index < NOTIFICATION_MAX_IDS; Index++) {
64 if (Service->ServiceBits[Index].InUse && (Service->ServiceBits[Index].IdNum == IdNum)) {
65 return Index;
66 }
67 }
68
69 return NOTIFICATION_ID_NOT_FOUND;
70}
71
72/**
73 Adds or removes service bit information to the local notification services struct array
74
75 @param Destroy Whether or not we are adding or removing bit information
76 @param Request The incoming message containing the bit information
77 @param Service The service we are updating bit information for
78
79 @retval NOTIFICATION_STATUS_SUCCESS Success
80 @retval NOTIFICATION_STATUS_INVALID_PARAMETER Invalid parameter
81
82**/
83STATIC
84NotificationStatus
85UpdateServiceBits (
86 BOOLEAN Destroy,
87 DIRECT_MSG_ARGS_EX *Request,
88 NotifService *Service
89 )
90{
91 NotificationStatus ReturnVal;
92 INT8 FoundIndex;
93 UINT8 IdIndex;
94 UINT8 NumBits;
95 UINTN *Mappings;
96 UINT8 MappingIndex;
97 UINT32 NotificationId;
98 UINT32 BitmapBitNum;
99 BOOLEAN EmptyFound;
100 NotifService TempService;
101 UINT64 TempBitmask;
102
103 /* Validate the incoming function parameters */
104 if ((Request == NULL) || (Service == NULL)) {
105 return NOTIFICATION_STATUS_INVALID_PARAMETER;
106 }
107
108 NumBits = Request->Arg3;
109 Mappings = &Request->Arg4;
110
111 /* You must be setting/destroying at least one bit and no more than the service supports */
112 if ((NumBits <= 0) || (NumBits > NOTIFICATION_MAX_IDS)) {
113 DEBUG ((DEBUG_ERROR, "Invalid NumBits: %x\n", NumBits));
114 return NOTIFICATION_STATUS_INVALID_PARAMETER;
115 }
116
117 ReturnVal = NOTIFICATION_STATUS_SUCCESS;
118
119 /* Copy the current service structure and global bitmask to the temporaries */
120 CopyMem (&TempService, Service, sizeof (NotifService));
121 TempBitmask = GlobalBitmask;
122
123 /* Need to go through all of the setup bits and update the structure */
124 for (MappingIndex = 0; MappingIndex < NumBits; MappingIndex++) {
125 NotificationId = Mappings[MappingIndex];
126 BitmapBitNum = (UINT64)Mappings[MappingIndex] >> 32;
127 FoundIndex = IsMatchingId (NotificationId, &TempService);
128
129 if (Destroy) {
130 /* If we can not find the ID to destroy, it is an error */
131 if (FoundIndex == NOTIFICATION_ID_NOT_FOUND) {
132 DEBUG ((DEBUG_ERROR, "Invalid Destroy ID: %x Not Found\n", NotificationId));
133 ReturnVal = NOTIFICATION_STATUS_INVALID_PARAMETER;
134 break;
135 /* If the bitmask bit is not set, it is an error */
136 } else if (!(GlobalBitmask & (1 << BitmapBitNum))) {
137 DEBUG ((DEBUG_ERROR, "Invalid Destroy Bitmap Bit: %x Not Set\n", BitmapBitNum));
138 ReturnVal = NOTIFICATION_STATUS_INVALID_PARAMETER;
139 break;
140 } else {
141 /* Clear the data */
142 TempService.ServiceBits[FoundIndex].BitNum = 0;
143 TempService.ServiceBits[FoundIndex].IdNum = 0;
144 TempService.ServiceBits[FoundIndex].InUse = FALSE;
145 TempBitmask &= ~(1 << BitmapBitNum);
146 }
147 } else {
148 /* If we can find the ID to setup, it is an error */
149 if (FoundIndex != NOTIFICATION_ID_NOT_FOUND) {
150 DEBUG ((DEBUG_ERROR, "Invalid Setup ID: %x Found\n", NotificationId));
151 ReturnVal = NOTIFICATION_STATUS_INVALID_PARAMETER;
152 break;
153 /* If the bitmas bit is set, it is an error */
154 } else if (GlobalBitmask & (1 << BitmapBitNum)) {
155 DEBUG ((DEBUG_ERROR, "Invalid Setup Bitmap Bit: %x Set\n", BitmapBitNum));
156 ReturnVal = NOTIFICATION_STATUS_INVALID_PARAMETER;
157 break;
158 } else {
159 /* Need to loop through the bits within the structure and find an empty location */
160 EmptyFound = FALSE;
161 for (IdIndex = 0; IdIndex < NOTIFICATION_MAX_IDS; IdIndex++) {
162 if (!TempService.ServiceBits[IdIndex].InUse) {
163 EmptyFound = TRUE;
164 break;
165 }
166 }
167
168 /* If we can not find an empty space, it is an error */
169 if (!EmptyFound) {
170 DEBUG ((DEBUG_ERROR, "Setup Failed - No Memory Available\n"));
171 ReturnVal = NOTIFICATION_STATUS_NO_MEM;
172 break;
173 } else {
174 /* Update the data */
175 TempService.ServiceBits[IdIndex].BitNum = BitmapBitNum;
176 TempService.ServiceBits[IdIndex].IdNum = NotificationId;
177 TempService.ServiceBits[IdIndex].InUse = TRUE;
178 TempBitmask |= (1 << BitmapBitNum);
179 }
180 }
181 }
182 }
183
184 /* Copy the temporaries back if everything was successful */
185 if (ReturnVal == NOTIFICATION_STATUS_SUCCESS) {
186 CopyMem (Service, &TempService, sizeof (NotifService));
187 GlobalBitmask = TempBitmask;
188 }
189
190 return ReturnVal;
191}
192
193/**
194 Handler for Notification Query command
195
196 @param Request The incoming message
197 @param Response The outgoing message
198
199 @retval NOTIFICATION_STATUS_GENERIC_ERROR Unsupported Function
200
201**/
202STATIC
203NotificationStatus
204QueryHandler (
205 DIRECT_MSG_ARGS_EX *Request,
206 DIRECT_MSG_ARGS_EX *Response
207 )
208{
209 /* TODO: Remove when/if we decided to support Query */
210 Response->Arg0 = NOTIFICATION_STATUS_GENERIC_ERROR;
211 DEBUG ((DEBUG_ERROR, "Notification Service Query Unsupported\n"));
212 return NOTIFICATION_STATUS_GENERIC_ERROR;
213
214 UINT8 Index;
215 UINT8 NumIds;
216 NotifService *Service;
217 UINT8 Uuid[16];
218 NotificationStatus ReturnVal;
219
220 Service = NULL;
221 ReturnVal = NOTIFICATION_STATUS_INVALID_PARAMETER;
222
223 /* Extract the UUID from the message */
224 NotificationServiceExtractUuid (Request, Uuid);
225
226 /* Attempt to find the UUID within our list */
227 for (Index = 0; Index < NOTIFICATION_MAX_SERVICES; Index++) {
228 if (!CompareMem (Uuid, NotificationServices[Index].ServiceUuid, sizeof (Uuid))) {
229 Service = &NotificationServices[Index];
230 break;
231 }
232 }
233
234 /* Check for a valid UUID */
235 if (Service != NULL) {
236 /* Count the number of IDs that are in use */
237 NumIds = 0;
238 for (Index = 0; Index < NOTIFICATION_MAX_IDS; Index++) {
239 if (Service->ServiceBits[Index].InUse) {
240 NumIds++;
241 }
242 }
243
244 Response->Arg1 = NumIds;
245 ReturnVal = NOTIFICATION_STATUS_SUCCESS;
246 } else {
247 DEBUG ((DEBUG_ERROR, "Service Query Failed - Error Code: %x\n", ReturnVal));
248 }
249
250 Response->Arg0 = ReturnVal;
251 return ReturnVal;
252}
253
254/**
255 Handler for Notification Setup command
256
257 @param Request The incoming message
258 @param Response The outgoing message
259
260 @retval NOTIFICATION_STATUS_SUCCESS Success
261 @retval NOTIFICATION_STATUS_INVALID_PARAMETER Invalid parameter
262
263**/
264STATIC
265NotificationStatus
266SetupHandler (
267 DIRECT_MSG_ARGS_EX *Request,
268 DIRECT_MSG_ARGS_EX *Response
269 )
270{
271 UINT8 Index;
272 NotifService *Service;
273 UINT8 Uuid[16];
274 NotificationStatus ReturnVal;
275
276 Service = NULL;
277 ReturnVal = NOTIFICATION_STATUS_NO_MEM;
278
279 /* Extract the UUID from the message */
280 NotificationServiceExtractUuid (Request, Uuid);
281
282 /* If we haven't stored the source and destination IDs, store them */
283 if (!IdsAcquired) {
284 SourceId = Request->SourceId;
285 DestinationId = Request->DestinationId;
286 IdsAcquired = TRUE;
287 }
288
289 /* Attempt to find the UUID within our list */
290 for (Index = 0; Index < NOTIFICATION_MAX_SERVICES; Index++) {
291 if (!CompareMem (Uuid, NotificationServices[Index].ServiceUuid, sizeof (Uuid))) {
292 Service = &NotificationServices[Index];
293 break;
294 }
295 }
296
297 /* The UUID was not found in the list, attempt to find an empty location to add it */
298 if (Service == NULL) {
299 for (Index = 0; Index < NOTIFICATION_MAX_SERVICES; Index++) {
300 if (!NotificationServices[Index].InUse) {
301 Service = &NotificationServices[Index];
302 CopyMem (Service->ServiceUuid, Uuid, sizeof (Uuid));
303 Service->InUse = TRUE;
304 break;
305 }
306 }
307 }
308
309 /* Check for a valid UUID and validate the input parameters */
310 if (Service != NULL) {
311 ReturnVal = UpdateServiceBits (FALSE, Request, Service);
312 } else {
313 DEBUG ((DEBUG_ERROR, "Service Setup Failed - Error Code: %x\n", ReturnVal));
314 }
315
316 Response->Arg0 = ReturnVal;
317 return ReturnVal;
318}
319
320/**
321 Handler for Notification Destroy command
322
323 @param Request The incoming message
324 @param Response The outgoing message
325
326 @retval NOTIFICATION_STATUS_SUCCESS Success
327 @retval NOTIFICATION_STATUS_INVALID_PARAMETER Invalid parameter
328
329**/
330STATIC
331NotificationStatus
332DestroyHandler (
333 DIRECT_MSG_ARGS_EX *Request,
334 DIRECT_MSG_ARGS_EX *Response
335 )
336{
337 UINT8 Index;
338 NotifService *Service;
339 UINT8 Uuid[16];
340 NotificationStatus ReturnVal;
341
342 Service = NULL;
343 ReturnVal = NOTIFICATION_STATUS_INVALID_PARAMETER;
344
345 /* Extract the UUID from the message */
346 NotificationServiceExtractUuid (Request, Uuid);
347
348 /* Attempt to find the UUID within our list */
349 for (Index = 0; Index < NOTIFICATION_MAX_SERVICES; Index++) {
350 if (!CompareMem (Uuid, NotificationServices[Index].ServiceUuid, sizeof (Uuid))) {
351 Service = &NotificationServices[Index];
352 break;
353 }
354 }
355
356 /* Check for a valid UUID and validate the input parameters */
357 if (Service != NULL) {
358 ReturnVal = UpdateServiceBits (TRUE, Request, Service);
359 } else {
360 DEBUG ((DEBUG_ERROR, "Service Destroy Failed - Error Code: %x\n", ReturnVal));
361 }
362
363 Response->Arg0 = ReturnVal;
364 return ReturnVal;
365}
366
367/**
368 Initializes the Notification service
369
370**/
371VOID
372NotificationServiceInit (
373 VOID
374 )
375{
376 UINT8 Index;
377
378 /* Initialize Global Values */
379 IdsAcquired = FALSE;
380 SourceId = 0;
381 DestinationId = 0;
382 GlobalBitmask = 0;
383
384 for (Index = 0; Index < NOTIFICATION_MAX_SERVICES; Index++) {
385 SetMem (&NotificationServices[Index], sizeof (NotifService), 0);
386 }
387}
388
389/**
390 Deinitializes the Notification service
391
392**/
393VOID
394NotificationServiceDeInit (
395 VOID
396 )
397{
398 /* Nothing to DeInit */
399}
400
401/**
402 Handler for Notification service commands
403
404 @param Request The incoming message
405 @param Response The outgoing message
406
407**/
408VOID
409NotificationServiceHandle (
410 DIRECT_MSG_ARGS_EX *Request,
411 DIRECT_MSG_ARGS_EX *Response
412 )
413{
414 UINT64 Opcode;
415
416 /* Validate the input parameters before attempting to dereference or pass them along */
417 if ((Request == NULL) || (Response == NULL)) {
418 return;
419 }
420
421 Opcode = Request->Arg0;
422
423 switch (Opcode) {
424 case NOTIFICATION_OPCODE_QUERY:
425 QueryHandler (Request, Response);
426 break;
427
428 case NOTIFICATION_OPCODE_SETUP:
429 SetupHandler (Request, Response);
430 break;
431
432 case NOTIFICATION_OPCODE_DESTROY:
433 DestroyHandler (Request, Response);
434 break;
435
436 default:
437 Response->Arg0 = NOTIFICATION_STATUS_INVALID_PARAMETER;
438 DEBUG ((DEBUG_ERROR, "Invalid Notification Service Opcode\n"));
439 break;
440 }
441}
442
443/**
444 Calls NotificationSet on the given ID with the given flag
445
446 @param Id The ID to trigger the event on
447 @param ServiceUuid The service containing the ID to trigger
448 @param Flag The NotificationSet flag to use
449
450 @retval NOTIFICATION_STATUS_SUCCESS Success
451 @retval NOTIFICATION_STATUS_INVALID_PARAMETER Invalid parameter
452 @retval NOTIFICATION_STATUS_GENERIC_ERROR NotificationSet failed
453
454**/
455NotificationStatus
456NotificationServiceIdSet (
457 UINT32 Id,
458 UINT8 *ServiceUuid,
459 UINT32 Flag
460 )
461{
462 NotifService *Service;
463 NotificationStatus ReturnVal;
464 UINT8 Index;
465 UINT64 Bitmask;
466 EFI_STATUS Status;
467
468 /* Validate the incoming function parameters */
469 if (ServiceUuid == NULL) {
470 return NOTIFICATION_STATUS_INVALID_PARAMETER;
471 }
472
473 Service = NULL;
474 ReturnVal = NOTIFICATION_STATUS_INVALID_PARAMETER;
475
476 /* Attempt to find the UUID within our list */
477 for (Index = 0; Index < NOTIFICATION_MAX_SERVICES; Index++) {
478 if (!CompareMem (ServiceUuid, NotificationServices[Index].ServiceUuid, sizeof (NotificationServices[Index].ServiceUuid))) {
479 Service = &NotificationServices[Index];
480 break;
481 }
482 }
483
484 /* UUID was found */
485 if (Service != NULL) {
486 /* Attempt to find the logical ID within the mapped list */
487 for (Index = 0; Index < NOTIFICATION_MAX_IDS; Index++) {
488 if (Service->ServiceBits[Index].IdNum == Id) {
489 Bitmask = (1 << Service->ServiceBits[Index].BitNum);
490 Status = FfaNotificationSet (SourceId, Flag, Bitmask);
491 if (EFI_ERROR (Status)) {
492 ReturnVal = NOTIFICATION_STATUS_GENERIC_ERROR;
493 } else {
494 ReturnVal = NOTIFICATION_STATUS_SUCCESS;
495 }
496
497 break;
498 }
499 }
500 }
501
502 return ReturnVal;
503}
504
505/**
506 Extracts the UUID from the message arguments
507
508 @param Request The incoming message to extract the UUID from
509 @param Uuid The UUID to populate
510
511**/
512VOID
513NotificationServiceExtractUuid (
514 DIRECT_MSG_ARGS_EX *Request,
515 UINT8 *Uuid
516 )
517{
518 UINT64 UuidLo;
519 UINT64 UuidHi;
520 UINT8 Index;
521 UINT8 UuidHiByte;
522 UINT8 UuidLoByte;
523
524 /* Validate the incoming function parameters */
525 if ((Request == NULL) || (Uuid == NULL)) {
526 return;
527 }
528
529 UuidLo = Request->Arg1;
530 UuidHi = Request->Arg2;
531
532 /* Copy the upper 8 bytes */
533 for (Index = 0; Index < 8; Index++) {
534 UuidHiByte = (UINT8)(UuidHi >> ((7 - Index) * 8));
535 Uuid[Index] = UuidHiByte;
536 }
537
538 /* Copy the lower 8 bytes */
539 for (Index = 8; Index < 16; Index++) {
540 UuidLoByte = (UINT8)(UuidLo >> ((15 - Index) * 8));
541 Uuid[Index] = UuidLoByte;
542 }
543}