92 lines
2.2 KiB
C
92 lines
2.2 KiB
C
/* Copyright (c) 2021 Apple Inc. All rights reserved. */
|
|
|
|
#include <kern/clock.h>
|
|
#include <libkern/libkern.h>
|
|
#include <machine/machine_routines.h>
|
|
#include <os/system_event_log.h>
|
|
|
|
static const char *
|
|
convert_subsystem_to_string(uint8_t subsystem)
|
|
{
|
|
switch (subsystem) {
|
|
case SYSTEM_EVENT_SUBSYSTEM_LAUNCHD:
|
|
return "launchd";
|
|
case SYSTEM_EVENT_SUBSYSTEM_TEST:
|
|
return "test";
|
|
case SYSTEM_EVENT_SUBSYSTEM_NVRAM:
|
|
return "nvram";
|
|
case SYSTEM_EVENT_SUBSYSTEM_PROCESS:
|
|
return "process";
|
|
case SYSTEM_EVENT_SUBSYSTEM_PMRD:
|
|
return "iopmrd";
|
|
default:
|
|
break;
|
|
}
|
|
return "UNKNOWN";
|
|
}
|
|
|
|
static const char *
|
|
convert_type_to_string(uint8_t type)
|
|
{
|
|
switch (type) {
|
|
case SYSTEM_EVENT_TYPE_INFO:
|
|
return "INFO";
|
|
case SYSTEM_EVENT_TYPE_ERROR:
|
|
return "ERROR";
|
|
default:
|
|
break;
|
|
}
|
|
return "UNKNOWN";
|
|
}
|
|
|
|
/* We don't want to interfere with critical tasks.
|
|
* Skip recording this event if:
|
|
* 1. Interrupts are disabled.
|
|
* 2. We are not in a panic.
|
|
* A suggested improvement is adding events to an MPSC queue to log later on (rdar://84678724).
|
|
*/
|
|
static bool
|
|
is_recording_allowed(void)
|
|
{
|
|
return ml_get_interrupts_enabled() || panic_active();
|
|
}
|
|
|
|
static void
|
|
_record_system_event_internal(uint8_t type, uint8_t subsystem, const char *event, const char *payload)
|
|
{
|
|
const char *type_string = convert_type_to_string(type);
|
|
const char *subsystem_string = convert_subsystem_to_string(subsystem);
|
|
|
|
uint64_t nanosecs;
|
|
const uint64_t timestamp = mach_continuous_time();
|
|
absolutetime_to_nanoseconds(timestamp, &nanosecs);
|
|
|
|
printf("[System Event] [%llu] [%s] [Subsystem: %s] [Event: %.*s] %s\n", timestamp, type_string, subsystem_string, SYSTEM_EVENT_EVENT_MAX, event, payload);
|
|
}
|
|
|
|
void
|
|
record_system_event(uint8_t type, uint8_t subsystem, const char *event, const char *format, ...)
|
|
{
|
|
if (!is_recording_allowed()) {
|
|
return;
|
|
}
|
|
|
|
va_list args;
|
|
va_start(args, format);
|
|
char payload[SYSTEM_EVENT_PAYLOAD_MAX];
|
|
|
|
vsnprintf(payload, sizeof(payload), format, args);
|
|
va_end(args);
|
|
|
|
_record_system_event_internal(type, subsystem, event, payload);
|
|
}
|
|
|
|
void
|
|
record_system_event_no_varargs(uint8_t type, uint8_t subsystem, const char *event, const char *payload)
|
|
{
|
|
if (!is_recording_allowed()) {
|
|
return;
|
|
}
|
|
|
|
_record_system_event_internal(type, subsystem, event, payload);
|
|
}
|