xref: /xnu-11417.140.69/libkern/os/system_event_log.c (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1 /* Copyright (c) 2021 Apple Inc. All rights reserved. */
2 
3 #include <kern/clock.h>
4 #include <libkern/libkern.h>
5 #include <machine/machine_routines.h>
6 #include <os/system_event_log.h>
7 
8 static const char *
convert_subsystem_to_string(uint8_t subsystem)9 convert_subsystem_to_string(uint8_t subsystem)
10 {
11 	switch (subsystem) {
12 	case SYSTEM_EVENT_SUBSYSTEM_LAUNCHD:
13 		return "launchd";
14 	case SYSTEM_EVENT_SUBSYSTEM_TEST:
15 		return "test";
16 	case SYSTEM_EVENT_SUBSYSTEM_NVRAM:
17 		return "nvram";
18 	case SYSTEM_EVENT_SUBSYSTEM_PROCESS:
19 		return "process";
20 	case SYSTEM_EVENT_SUBSYSTEM_PMRD:
21 		return "iopmrd";
22 	default:
23 		break;
24 	}
25 	return "UNKNOWN";
26 }
27 
28 static const char *
convert_type_to_string(uint8_t type)29 convert_type_to_string(uint8_t type)
30 {
31 	switch (type) {
32 	case SYSTEM_EVENT_TYPE_INFO:
33 		return "INFO";
34 	case SYSTEM_EVENT_TYPE_ERROR:
35 		return "ERROR";
36 	default:
37 		break;
38 	}
39 	return "UNKNOWN";
40 }
41 
42 /* We don't want to interfere with critical tasks.
43  * Skip recording this event if:
44  *   1. Interrupts are disabled.
45  *   2. We are not in a panic.
46  * A suggested improvement is adding events to an MPSC queue to log later on (rdar://84678724).
47  */
48 static bool
is_recording_allowed(void)49 is_recording_allowed(void)
50 {
51 	return ml_get_interrupts_enabled() || panic_active();
52 }
53 
54 static void
_record_system_event_internal(uint8_t type,uint8_t subsystem,const char * event,const char * payload)55 _record_system_event_internal(uint8_t type, uint8_t subsystem, const char *event, const char *payload)
56 {
57 	const char *type_string = convert_type_to_string(type);
58 	const char *subsystem_string = convert_subsystem_to_string(subsystem);
59 
60 	uint64_t nanosecs;
61 	const uint64_t timestamp = mach_continuous_time();
62 	absolutetime_to_nanoseconds(timestamp, &nanosecs);
63 
64 	printf("[System Event] [%llu] [%s] [Subsystem: %s] [Event: %.*s] %s\n", timestamp, type_string, subsystem_string, SYSTEM_EVENT_EVENT_MAX, event, payload);
65 }
66 
67 void
record_system_event(uint8_t type,uint8_t subsystem,const char * event,const char * format,...)68 record_system_event(uint8_t type, uint8_t subsystem, const char *event, const char *format, ...)
69 {
70 	if (!is_recording_allowed()) {
71 		return;
72 	}
73 
74 	va_list args;
75 	va_start(args, format);
76 	char payload[SYSTEM_EVENT_PAYLOAD_MAX];
77 
78 	vsnprintf(payload, sizeof(payload), format, args);
79 	va_end(args);
80 
81 	_record_system_event_internal(type, subsystem, event, payload);
82 }
83 
84 void
record_system_event_no_varargs(uint8_t type,uint8_t subsystem,const char * event,const char * payload)85 record_system_event_no_varargs(uint8_t type, uint8_t subsystem, const char *event, const char *payload)
86 {
87 	if (!is_recording_allowed()) {
88 		return;
89 	}
90 
91 	_record_system_event_internal(type, subsystem, event, payload);
92 }
93