Here and there: boot.efi printing now and then.   UPDATED: 31.01.2018 with fixes to certain misunderstandings and relevant NVRAM variables to control boot.efi logging behaviour.   Scroll all the way down to "How is this configured" if you need boot.efi debug printing.   Apple developers improved boot.efi printing quite a lot as of High Sierra. The good thing is that we could make a good use of it, the bad thing, it is not too obvious.   Just like everything else boot.efi follows edk2-like error level reporting. In release boot.efi only DEBUG_ERROR (0x80000000) is available, the rest are stripped.   First of all, boot.efi has an unholy amount of different print functions for all the needs. So it will be a good start to list them. The function names may not be ideal, but I left the examples with strings to let one get an idea.   1. VOID PerfRecordPrint(CONST CHAR8 *Format, ...)   There are tons of its calls, for example: PerfRecordPrint("Start"); PerfRecordPrint("Start OSName"); PerfRecordPrint("End OSName"); PerfRecordPrint("Start LoadCoreStorageConfiguration");   Its designation is to measure how much it took for boot.efi to execute each certain step and provide Apple the performance details. Prior to 10.13 it was only possible to use it to log to NVRAM (efiboot-perf-record-data, efiboot-perf-record-data-size). Starting with 10.13 it may also print via logging 'drivers', which print via different implementations.   2. VOID AppleLoggingPrintAll(UINTN ErrorLevel, CONST CHAR8 *Format, ...)   Known for printing especially crtitical messages like: AppleLoggingPrintAll(DEBUG_ERROR, "This version of Mac OS X is not supported on this platform!\n"); AppleLoggingPrintAll(DEBUG_ERROR, "This system was automatically rebooted after panic\n");   Prior to 10.13 it was an unconditional formatted print via gST->ConOut or gST->StdErr if unavailable. Starting with 10.13 it prints via logging 'drivers', which print via different implementations. AppleLoggingPrintAll is designed to print via all the 'drivers'.   3. VOID FatalError(CONST CHAR8 *Format, ...)   Known usages, for example: FatalError("Can not initialize console\n"); FatalError("ERROR!!! Recovery Image verification fail with status [0x%llx]\n", Status); FatalError("Couldn't allocate bootArgs\n");   This is the well known print the error, sleep for 10 secs, and reboot. Prior to 10.13 it used an unconditional formatted print via gST->ConOut or gST->StdErr if unavailable. Starting with 10.13 it also prints via logging 'drivers', all of them.   4. VOID AppleLoggingPrintAllStyled(UINTN Level, CONST CHAR8 *Format, ...)   AppleLoggingPrintAllStyled(DEBUG_ERROR, "ERROR!!! Load prelinked kernel with status 0x%lx\n", Status); AppleLoggingPrintAllStyled(DEBUG_ERROR, "(no root UUID found for boot device)\n"); AppleLoggingPrintAllStyled(DEBUG_ERROR, "Boot failed, sleeping for 10 seconds before exiting...\n"); AppleLoggingPrintAllStyled(0x80000000ui64, "ERROR!!! Uncompress prelinked kernel\n");   This one has always been printing via all of the logging 'drivers', starting with 10.11 at least.   Main internal implementation   Prior to 10.13 most of the prints went through a direct call through gST->ConOut/gST->StdErr, and printing drivers were almost unused and left unnoticed. Starting with 10.13 printing drivers are for almost everything, and we need to take good care of them. Interestingly they could also do additional formatting to the output (like timestamps).   These functions are the main functions Apple uses to print stuff. To fully understand them one needs to go deeper into the implementation.   The idea is to have a formatter function similar to vprintf. void AppleLoggingFormatter(CONST CHAR8 *Format, APPLE_LOGGING_PUTCHAR PutChar, AppleLoggingState *State, va_list *Args) The arguments are as follows: - a format string; - some internal state; - a putchar-like function, which will use the state; - a variable list of arguments.   Prior to 10.13 everything went through a simple putchar function, that did not even need a state. All the above functions but PerfRecordPrint would invoke DirectLoggingPrintf or alike under some condition and print to gST->ConOut or gST->ConOut.         The exceptional PerfRecordPrint required a special nvram variable (efiboot-perf-record) to be present. When it was there, boot.efi would print to a memory buffer until the very end, and will later store its data in efiboot-perf-record-data/efiboot-perf-record-data-size variables. As a bonus it is also passed via BootArgs structure, so a bootloader can easily obtain this data too.         Printing drivers used throughout 10.13   While printing drivers are not new to 10.13, and they existed in the previous operating systems, nothing really used them. Currently there are three, each exposing 2 funcs to enable/disable and its own bit used in logging usage mask.   1 — AppleLoggingConOutOrErrSet/AppleLoggingConOutOrErrPrint (classical ConOut or StdErr on failure) 2 - AppleLoggingStdErrSet/AppleLoggingStdErrPrint (StdErr or serial?) 4 - AppleLoggingFileSet/AppleLoggingFilePrint (BOOTER.LOG/BOOTER.OLD file on EFI partition)   So, from now on to be able to print via either of the driver one must do 3 things: - include the bit in the printer driver mask (this is done pretty much everywhere); - enable the driver itself by calling its Set function with 0 argument; - pray that the driver works fine   Relevant decompiled code is included below:         So, the functions are now modified to print their output via 2 new interfaces: void AppleLoggingPrintfStyled(UINTN PrinterMask, UINTN Level, const char *Format, va_list *Args); void AppleLoggingPrintf(UINTN PrinterMask, UINTN Level, const char *Format, va_list *Args);   PrinterMask is responsible for choosing the drivers to use. Currently Apple seems to pass 0x37 everywhere. So it means that by default all the drivers should at least try printing. The only difference between Styled and non-styled is that styled depending on gBootArgDebug.variable value may print a timestamp.         What are the changes to the top functions? There is nothing interesting besides the use of AppleLoggingPrintfs. But FatalError and PerfRecordPrint got something special. First one no longer uses direct ConOut/StdErr logging for printing errors, but has a well-known "does printf work??" message going through it. So we can conclude that AppleLoggingPrintf does not work on most of hacks. Second one will now use AppleLoggingPrintfStyled to print debug messages, which means if AppleLoggingPrintfStyled begins to work, we will be able to print the whole boot.efi trace log onscreen.         How is this configured?   Initially I confused this part quite a lot due to various circumstances . Now it is much better. To configure the driver logging boot.efi uses nvram bootercfg and bootercfg-once variables, which are very similar to boot-args. bootercfg-once is a way to change the debugging for a single boot only, and it is read and deleted by boot.efi only if bootercfg is not present.   The accepted values for all the arguments are hexadecimal 64-bit values with or without 0x prefix: — log=VALUE — debug=VALUE — level=VALUE — kc-read-size=VALUE   For log the valid bits are enabled log drivers: 1 — AppleLoggingConOutOrErrSet/AppleLoggingConOutOrErrPrint (classical ConOut or StdErr on failure) 2 — AppleLoggingStdErrSet/AppleLoggingStdErrPrint (StdErr or serial?) 4 — AppleLoggingFileSet/AppleLoggingFilePrint (BOOTER.LOG/BOOTER.OLD file on EFI partition)   For debug the valid bits are: 1 — enables print something to BOOTER.LOG (stripped code implies there may be a crash) 2 — enables perf logging to /efi/debug-log in the device three 4 — enables timestamp printing for styled printf calls   Thus to quickly disable the logging functionality in -v mode in boot.efi you could use sudo nvram bootercfg="log=0".   For level the value is the verbosity level of DEBUG output. Since everything but 0x80000000 is stripped from the binary, and this is the default value, it is not very handy.   For kc-reead-size the value is a chunk size used for buffered i/o from the network (unsupported obviously) or the disk for stuff like prelinkedkernel reading. By default it is set to 1MB (0x100000), but you may try to increase it for a millisecond faster booting   Interanlly there are three functions to configure printing driver usage, in particular these: - AppleLoggingSet (a dedicated func to speficific drivers on or off) - AppleLoggingEnable - AppleLoggingDisable   The only usage of the first one is in boot key parsing code. Pressing Cmd + V (verbose mode) will enable the 1st driver (classical ConOut or StdErr on failure). It is really weird, because -v in boot-args does not do it, but I guess Cmd + V is considered more special than -v.   Which adds to the top of the ice-berg is that AppleLoggingDisable is called before boot.efi goes down or booter services will be no longer available due to os start: - right before rebooting into Recovery - right before chainloading a second boot.efi - before printing "Boot failed, sleeping for 10 seconds" - during memory map allocation close to XNU start - right before EXIT_BOOT_SERVICES         To unconditionally and quickly enable the debug log in 10.13 one may still patch the check in the beginning of the logger function (ConOut/StdErr method). But I suppose it will be better to implement some interface to set bootercfg from Clover (or at least stop it from messing with it): 48 81 EC 50 01 00 00 80 3D -> 48 81 EC 50 01 00 00 EB 07