OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OpenCoreUefiAudio.c
Go to the documentation of this file.
1
15#include <Library/OcMainLib.h>
16
17#include <Guid/AppleVariable.h>
18#include <Guid/OcVariable.h>
19#include <Guid/GlobalVariable.h>
21
22#include <Library/BaseLib.h>
23#include <Library/DebugLib.h>
24#include <Library/DevicePathLib.h>
25#include <Library/MemoryAllocationLib.h>
30#include <Library/OcAudioLib.h>
31#include <Library/OcInputLib.h>
35#include <Library/OcCpuLib.h>
42#include <Library/OcMiscLib.h>
43#include <Library/OcSmcLib.h>
44#include <Library/OcOSInfoLib.h>
45#include <Library/PrintLib.h>
46#include <Library/UefiBootServicesTableLib.h>
47#include <Library/UefiLib.h>
48#include <Library/UefiRuntimeServicesTableLib.h>
49
50typedef struct OC_AUDIO_FILE_ {
51 UINT8 *Buffer;
52 UINT32 Size;
54
56
57STATIC
58VOID *
60 IN OC_STORAGE_CONTEXT *Storage,
61 IN CONST CHAR8 *BasePath,
62 IN CONST CHAR8 *BaseType,
63 IN BOOLEAN Localised,
64 IN CONST CHAR8 *Extension,
65 IN APPLE_VOICE_OVER_LANGUAGE_CODE LanguageCode,
66 OUT UINT32 *BufferSize
67 )
68{
69 EFI_STATUS Status;
71 VOID *Buffer;
72
73 if (Localised) {
74 Status = OcUnicodeSafeSPrint (
76 sizeof (FilePath),
77 OPEN_CORE_AUDIO_PATH "%a_%a_%a.%a",
78 BaseType,
79 OcLanguageCodeToString (LanguageCode),
80 BasePath,
81 Extension
82 );
83 ASSERT_EFI_ERROR (Status);
84
85 if (!OcStorageExistsFileUnicode (Storage, FilePath)) {
86 Status = OcUnicodeSafeSPrint (
88 sizeof (FilePath),
89 OPEN_CORE_AUDIO_PATH "%a_%a_%a.%a",
90 BaseType,
92 BasePath,
93 Extension
94 );
95 ASSERT_EFI_ERROR (Status);
96
97 if (!OcStorageExistsFileUnicode (Storage, FilePath)) {
98 return NULL;
99 }
100 }
101 } else {
102 Status = OcUnicodeSafeSPrint (
103 FilePath,
104 sizeof (FilePath),
105 OPEN_CORE_AUDIO_PATH "%a_%a.%a",
106 BaseType,
107 BasePath,
108 Extension
109 );
110 ASSERT_EFI_ERROR (Status);
111
112 if (!OcStorageExistsFileUnicode (Storage, FilePath)) {
113 return NULL;
114 }
115 }
116
118 Storage,
119 FilePath,
120 BufferSize
121 );
122 if (Buffer == NULL) {
123 return NULL;
124 }
125
126 return Buffer;
127}
128
129//
130// Note, currently we are not I/O bound, so implementing caching has no effect at all.
131// Reconsider it when we resolve lags with AudioDxe.
132//
133STATIC
134EFI_STATUS
135EFIAPI
137 IN VOID *Context,
138 IN CONST CHAR8 *BasePath,
139 IN CONST CHAR8 *BaseType,
140 IN BOOLEAN Localised,
141 IN APPLE_VOICE_OVER_LANGUAGE_CODE LanguageCode,
142 OUT UINT8 **Buffer,
143 OUT UINT32 *BufferSize,
144 OUT EFI_AUDIO_IO_PROTOCOL_FREQ *Frequency,
146 OUT UINT8 *Channels
147 )
148{
149 EFI_STATUS Status;
150 OC_STORAGE_CONTEXT *Storage;
151 UINT8 *FileBuffer;
152 UINT32 FileBufferSize;
153
154 if ((BasePath == NULL) || (BaseType == NULL) || (Buffer == NULL) || (*Buffer == NULL)) {
155 DEBUG ((DEBUG_ERROR, "OC: Illegal wave parameters\n"));
156 return EFI_INVALID_PARAMETER;
157 }
158
159 Storage = (OC_STORAGE_CONTEXT *)Context;
160
161 FileBuffer = OcAudioGetFileContents (
162 Storage,
163 BasePath,
164 BaseType,
165 Localised,
166 "mp3",
167 LanguageCode,
168 &FileBufferSize
169 );
170 if (FileBuffer == NULL) {
171 FileBuffer = OcAudioGetFileContents (
172 Storage,
173 BasePath,
174 BaseType,
175 Localised,
176 "wav",
177 LanguageCode,
178 &FileBufferSize
179 );
180 }
181
182 if (FileBuffer == NULL) {
183 DEBUG ((DEBUG_INFO, "OC: Wave %a %a cannot be found!\n", BaseType, BasePath));
184 return EFI_NOT_FOUND;
185 }
186
188
191 FileBuffer,
192 FileBufferSize,
193 (VOID **)Buffer,
194 BufferSize,
195 Frequency,
196 Bits,
197 Channels
198 );
199
200 FreePool (FileBuffer);
201
202 if (EFI_ERROR (Status)) {
203 DEBUG ((DEBUG_INFO, "OC: Wave %a %a cannot be decoded - %r!\n", BaseType, BasePath, Status));
204 return EFI_UNSUPPORTED;
205 }
206
207 return EFI_SUCCESS;
208}
209
210STATIC
211EFI_STATUS
212EFIAPI
214 IN VOID *Context,
215 IN UINT8 *Buffer
216 )
217{
218 FreePool (Buffer);
219 return EFI_SUCCESS;
220}
221
222STATIC
223BOOLEAN
225 IN CONST CHAR8 *Control
226 )
227{
228 EFI_STATUS Status;
229 UINT8 Muted;
230 UINTN Size;
231
232 if ((Control[0] == '\0') || (AsciiStrCmp (Control, "Auto") == 0)) {
233 Muted = 0;
234 Size = sizeof (Muted);
235 Status = gRT->GetVariable (
238 NULL,
239 &Size,
240 &Muted
241 );
242 DEBUG ((DEBUG_INFO, "OC: Using StartupMute %d for chime - %r\n", Muted, Status));
243 return Muted == 0;
244 }
245
246 if (AsciiStrCmp (Control, "Enabled") == 0) {
247 return TRUE;
248 }
249
250 return FALSE;
251}
252
253STATIC
254VOID
255EFIAPI
257 IN EFI_EVENT Event,
258 IN VOID *Context
259 )
260{
261 OC_AUDIO_PROTOCOL *OcAudio;
262
263 OcAudio = Context;
264 OcAudio->StopPlayback (OcAudio, TRUE);
265}
266
267VOID
269 IN OC_STORAGE_CONTEXT *Storage,
270 IN OC_GLOBAL_CONFIG *Config
271 )
272{
273 EFI_STATUS Status;
274 CHAR8 *AsciiDevicePath;
275 CHAR16 *UnicodeDevicePath;
276 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
277 OC_AUDIO_PROTOCOL *OcAudio;
278 UINT8 RawGain;
279 BOOLEAN Muted;
280 INT8 DecibelGain;
281 BOOLEAN TryConversion;
282
283 if (Config->Uefi.Audio.ResetTrafficClass) {
285 }
286
287 if (!Config->Uefi.Audio.AudioSupport) {
288 DEBUG ((DEBUG_INFO, "OC: Requested not to use audio\n"));
289 return;
290 }
291
292 Status = gBS->LocateProtocol (
294 NULL,
295 (VOID **)&mAudioDecodeProtocol
296 );
297 if (EFI_ERROR (Status)) {
298 DEBUG ((DEBUG_INFO, "OC: Cannot locate audio decoder protocol - %r\n", Status));
299 return;
300 }
301
302 DevicePath = NULL;
303 AsciiDevicePath = OC_BLOB_GET (&Config->Uefi.Audio.AudioDevice);
304 if (AsciiDevicePath[0] != '\0') {
305 UnicodeDevicePath = AsciiStrCopyToUnicode (AsciiDevicePath, 0);
306 if (UnicodeDevicePath != NULL) {
307 DevicePath = ConvertTextToDevicePath (UnicodeDevicePath);
308 FreePool (UnicodeDevicePath);
309 }
310
311 if (DevicePath == NULL) {
312 DEBUG ((DEBUG_INFO, "OC: Requested to use invalid audio device\n"));
313 return;
314 }
315 }
316
317 //
318 // NULL DevicePath means choose the first audio device available on the platform.
319 //
320
321 OcAudio = OcAudioInstallProtocols (FALSE, FALSE);
322 if (OcAudio == NULL) {
323 DEBUG ((DEBUG_INFO, "OC: Cannot locate OcAudio protocol\n"));
324 if (DevicePath != NULL) {
325 FreePool (DevicePath);
326 }
327
328 return;
329 }
330
331 Status = OcAudio->Connect (
332 OcAudio,
333 DevicePath,
334 Config->Uefi.Audio.AudioCodec,
335 Config->Uefi.Audio.AudioOutMask
336 );
337
338 if (DevicePath != NULL) {
339 FreePool (DevicePath);
340 }
341
342 if (EFI_ERROR (Status)) {
343 DEBUG ((DEBUG_INFO, "OC: Audio connection failed - %r\n", Status));
344 return;
345 }
346
348 &RawGain,
349 &DecibelGain,
350 &Muted,
351 &TryConversion
352 );
353
354 //
355 // Conversion will only be correct if current codec and channel(s)
356 // correspond to the saved raw gain parameter.
357 //
358 if (TryConversion) {
359 OcAudio->RawGainToDecibels (OcAudio, RawGain, &DecibelGain);
360 }
361
362 //
363 // Have a max. volume to limit very loud user volume during boot, as Apple do.
364 //
365 if (DecibelGain > Config->Uefi.Audio.MaximumGain) {
366 DEBUG ((
367 DEBUG_INFO,
368 "OC: Limiting gain %d dB -> %d dB\n",
369 DecibelGain,
370 Config->Uefi.Audio.MaximumGain
371 ));
372 DecibelGain = Config->Uefi.Audio.MaximumGain;
373 }
374
375 //
376 // Never disable audio assist sound completely, as it is vital for accessibility.
377 //
378 Status = OcAudio->SetDefaultGain (
379 OcAudio,
380 DecibelGain < Config->Uefi.Audio.MinimumAssistGain
381 ? Config->Uefi.Audio.MinimumAssistGain : DecibelGain
382 );
383
384 Status = OcAudio->SetProvider (
385 OcAudio,
388 Storage
389 );
390 if (EFI_ERROR (Status)) {
391 DEBUG ((DEBUG_INFO, "OC: Audio cannot set storage provider - %r\n", Status));
392 return;
393 }
394
395 OcAudio->SetDelay (
396 OcAudio,
397 Config->Uefi.Audio.SetupDelay
398 );
399
401
402 if ( !Muted
403 && (DecibelGain >= Config->Uefi.Audio.MinimumAudibleGain)
404 && OcShouldPlayChime (OC_BLOB_GET (&Config->Uefi.Audio.PlayChime)))
405 {
406 DEBUG ((DEBUG_INFO, "OC: Starting to play chime...\n"));
407 Status = OcAudio->PlayFile (
408 OcAudio,
411 FALSE,
412 DecibelGain,
413 TRUE,
414 FALSE
415 );
416 DEBUG ((DEBUG_INFO, "OC: Play chime started - %r\n", Status));
417 }
418
420}
EFI_GUID gAppleBootVariableGuid
#define APPLE_STARTUP_MUTE_VARIABLE_NAME
APPLE_VOICE_OVER_LANGUAGE_CODE
@ AppleVoiceOverLanguageEn
en
EFI_GUID gEfiAudioDecodeProtocolGuid
EFI_AUDIO_IO_PROTOCOL_FREQ
Definition AudioIo.h:104
EFI_AUDIO_IO_PROTOCOL_BITS
Definition AudioIo.h:93
DMG_FILEPATH_DEVICE_PATH FilePath
DMG_SIZE_DEVICE_PATH Size
#define OC_VOICE_OVER_AUDIO_FILE_VOICE_OVER_BOOT
Definition OcAudio.h:74
#define OC_VOICE_OVER_AUDIO_BASE_TYPE_OPEN_CORE
Definition OcAudio.h:38
VOID OcGetAmplifierGain(OUT UINT8 *RawGain, OUT INT8 *DecibelGain, OUT BOOLEAN *Muted, OUT BOOLEAN *TryConversion)
Definition OcAudioLib.c:166
CONST CHAR8 * OcLanguageCodeToString(IN APPLE_VOICE_OVER_LANGUAGE_CODE LanguageCode)
OC_AUDIO_PROTOCOL * OcAudioInstallProtocols(IN BOOLEAN Reinstall, IN BOOLEAN DisconnectHda)
Definition OcAudioLib.c:80
EFI_STATUS OcSetVoiceOverLanguage(CONST CHAR8 *Language OPTIONAL)
#define OPEN_CORE_AUDIO_PATH
EFI_BOOT_SERVICES * gBS
VOID ResetAudioTrafficClass(VOID)
VOID OcScheduleExitBootServices(IN EFI_EVENT_NOTIFY Handler, IN VOID *Context)
BOOLEAN OcStorageExistsFileUnicode(IN OC_STORAGE_CONTEXT *Context, IN CONST CHAR16 *FilePath)
VOID * OcStorageReadFileUnicode(IN OC_STORAGE_CONTEXT *Context, IN CONST CHAR16 *FilePath, OUT UINT32 *FileSize OPTIONAL)
#define OC_STORAGE_SAFE_PATH_MAX
CHAR16 * AsciiStrCopyToUnicode(IN CONST CHAR8 *String, IN UINTN Length)
Definition OcAsciiLib.c:119
EFI_STATUS EFIAPI OcUnicodeSafeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
#define OC_BLOB_GET(Blob)
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
STATIC EFI_STATUS EFIAPI OcAudioAcquireFile(IN VOID *Context, IN CONST CHAR8 *BasePath, IN CONST CHAR8 *BaseType, IN BOOLEAN Localised, IN APPLE_VOICE_OVER_LANGUAGE_CODE LanguageCode, OUT UINT8 **Buffer, OUT UINT32 *BufferSize, OUT EFI_AUDIO_IO_PROTOCOL_FREQ *Frequency, OUT EFI_AUDIO_IO_PROTOCOL_BITS *Bits, OUT UINT8 *Channels)
STATIC VOID EFIAPI OcAudioExitBootServices(IN EFI_EVENT Event, IN VOID *Context)
STATIC BOOLEAN OcShouldPlayChime(IN CONST CHAR8 *Control)
VOID OcLoadUefiAudioSupport(IN OC_STORAGE_CONTEXT *Storage, IN OC_GLOBAL_CONFIG *Config)
STATIC EFI_STATUS EFIAPI OcAudioReleaseFile(IN VOID *Context, IN UINT8 *Buffer)
STATIC VOID * OcAudioGetFileContents(IN OC_STORAGE_CONTEXT *Storage, IN CONST CHAR8 *BasePath, IN CONST CHAR8 *BaseType, IN BOOLEAN Localised, IN CONST CHAR8 *Extension, IN APPLE_VOICE_OVER_LANGUAGE_CODE LanguageCode, OUT UINT32 *BufferSize)
STATIC EFI_AUDIO_DECODE_PROTOCOL * mAudioDecodeProtocol
struct OC_AUDIO_FILE_ OC_AUDIO_FILE
EFI_RUNTIME_SERVICES * gRT
#define ASSERT(x)
Definition coder.h:55
EFI_AUDIO_DECODE_ANY DecodeAny
OC_AUDIO_SET_DELAY SetDelay
Definition OcAudio.h:264
OC_AUDIO_CONNECT Connect
Definition OcAudio.h:258
OC_AUDIO_STOP_PLAYBACK StopPlayback
Definition OcAudio.h:263
OC_AUDIO_RAW_GAIN_TO_DECIBELS RawGainToDecibels
Definition OcAudio.h:259
OC_AUDIO_PLAY_FILE PlayFile
Definition OcAudio.h:262
OC_AUDIO_SET_DEFAULT_GAIN SetDefaultGain
Definition OcAudio.h:260
OC_AUDIO_SET_PROVIDER SetProvider
Definition OcAudio.h:261