xref: /xnu-8792.61.2/libkern/os/system_event_log.c (revision 42e220869062b56f8d7d0726fd4c88954f87902c)
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 	default:
21 		break;
22 	}
23 	return "UNKNOWN";
24 }
25 
26 static const char *
convert_type_to_string(uint8_t type)27 convert_type_to_string(uint8_t type)
28 {
29 	switch (type) {
30 	case SYSTEM_EVENT_TYPE_INFO:
31 		return "INFO";
32 	case SYSTEM_EVENT_TYPE_ERROR:
33 		return "ERROR";
34 	default:
35 		break;
36 	}
37 	return "UNKNOWN";
38 }
39 
40 /* We don't want to interfere with critical tasks.
41  * Skip recording this event if:
42  *   1. Interrupts are disabled.
43  *   2. We are not in a panic.
44  * A suggested improvement is adding events to an MPSC queue to log later on (rdar://84678724).
45  */
46 static bool
is_recording_allowed(void)47 is_recording_allowed(void)
48 {
49 	return ml_get_interrupts_enabled() || panic_active();
50 }
51 
52 static void
_record_system_event_internal(uint8_t type,uint8_t subsystem,const char * event,const char * payload)53 _record_system_event_internal(uint8_t type, uint8_t subsystem, const char *event, const char *payload)
54 {
55 	const char *type_string = convert_type_to_string(type);
56 	const char *subsystem_string = convert_subsystem_to_string(subsystem);
57 
58 	uint64_t nanosecs;
59 	const uint64_t timestamp = mach_continuous_time();
60 	absolutetime_to_nanoseconds(timestamp, &nanosecs);
61 
62 	printf("[System Event] [%llu] [%s] [Subsystem: %s] [Event: %.*s] %s\n", timestamp, type_string, subsystem_string, SYSTEM_EVENT_EVENT_MAX, event, payload);
63 }
64 
65 void
record_system_event(uint8_t type,uint8_t subsystem,const char * event,const char * format,...)66 record_system_event(uint8_t type, uint8_t subsystem, const char *event, const char *format, ...)
67 {
68 	if (!is_recording_allowed()) {
69 		return;
70 	}
71 
72 	va_list args;
73 	va_start(args, format);
74 	char payload[SYSTEM_EVENT_PAYLOAD_MAX];
75 
76 	vsnprintf(payload, sizeof(payload), format, args);
77 	va_end(args);
78 
79 	_record_system_event_internal(type, subsystem, event, payload);
80 }
81 
82 void
record_system_event_no_varargs(uint8_t type,uint8_t subsystem,const char * event,const char * payload)83 record_system_event_no_varargs(uint8_t type, uint8_t subsystem, const char *event, const char *payload)
84 {
85 	if (!is_recording_allowed()) {
86 		return;
87 	}
88 
89 	_record_system_event_internal(type, subsystem, event, payload);
90 }
91