]>
git.saurik.com Git - apple/xnu.git/blob - tests/preoslog.c
e8615016cca4a233b31d1bbe39fecf3f558b7885
1 #include <darwintest.h>
2 #include <darwintest_utils.h>
3 #include <sys/sysctl.h>
8 * Any change to this structure must be reflected in iBoot / MacEFI / PanicDump / XNU Tests and vice versa.
10 typedef struct __attribute__((packed
)) {
11 uint32_t magic
; /* g_valid_magic if valid */
12 uint32_t size
; /* Size of the preoslog buffer including the header */
13 uint32_t offset
; /* Write pointer. Indicates where in the buffer new log entry would go */
14 uint8_t source
; /* Indicates who filled in the buffer (e.g. iboot vs MacEFI) */
15 uint8_t wrapped
; /* If equal to 1, the preoslog ring buffer wrapped at least once */
16 char data
[]; /* log buffer */
19 static const char* g_sysctl_kern_version
= "kern.version";
20 static const char* g_sysctl_kern_preoslog
= "kern.preoslog";
21 static const uint32_t g_valid_magic
= 'LSOP';
24 * Defines substrings to look up in preoslog buffer.
25 * To pass the test, one of the entries should match a substring in preoslog buffer.
27 static const char* g_preoslog_buffer_string
[] = {"serial output"};
30 check_for_substrings(const char* string
, size_t len
)
33 boolean_t res
= FALSE
;
35 for (i
= 0; i
< (sizeof(g_preoslog_buffer_string
) / sizeof(char*)); i
++) {
36 res
= res
|| strnstr(string
, g_preoslog_buffer_string
[i
], len
) == NULL
? FALSE
: TRUE
;
43 is_development_kernel(void)
47 size_t dev_size
= sizeof(dev
);
49 ret
= sysctlbyname("kern.development", &dev
, &dev_size
, NULL
, 0);
59 * 1. Development & Debug iBoot/macEFI provides a preoslog buffer.
60 * 2. Release iBoot/macEFI doesn't provide a presoslog buffer.
61 * 3. Development & Debug xnu provids kern.preoslog sysctl.
62 * 4. Release xnu doesn't provide kern.preoslog sysctl.
65 T_DECL(test_preoslog
, "Validate kern.preoslog sysctl has expected log content from the boot loader")
70 preoslog_header_t
*header
= NULL
;
72 const char *lower_buffer
= NULL
;
73 size_t lower_buffer_size
= 0;
74 const char *upper_buffer
= NULL
;
75 size_t upper_buffer_size
= 0;
76 boolean_t found
= FALSE
;
78 // kern.preoslog is writable
79 ret
= sysctlbyname(g_sysctl_kern_preoslog
, buffer
, &size
, &tmp
, sizeof(tmp
));
80 T_ASSERT_POSIX_SUCCESS(ret
, "kern.preoslog write check");
82 ret
= sysctlbyname(g_sysctl_kern_preoslog
, NULL
, &size
, NULL
, 0);
83 if (!is_development_kernel()) {
84 // kern.preoslog mustn't exist on release builds of xnu
85 T_ASSERT_NE(ret
, 0, "get size kern.preoslog ret != 0 on release builds");
86 T_ASSERT_POSIX_ERROR(ret
, ENOENT
, " get size kern.preoslog errno==ENOENT on release builds");
91 * Everything below is applicable only to development & debug xnu
94 T_ASSERT_POSIX_SUCCESS(ret
, "get size for kern.preoslog");
96 // No preoslog buffer available, valid case if iboot is release
100 buffer
= calloc(size
, sizeof(char));
101 T_ASSERT_NOTNULL(buffer
, "allocate buffer for preoslog");
103 ret
= sysctlbyname(g_sysctl_kern_preoslog
, buffer
, &size
, NULL
, 0);
104 T_ASSERT_POSIX_SUCCESS(ret
, "get preoslog buffer");
106 header
= (preoslog_header_t
*)buffer
;
107 T_ASSERT_EQ(header
->magic
, g_valid_magic
, "check preoslog header magic - expected %#x, given %#x", g_valid_magic
, header
->magic
);
108 T_ASSERT_EQ(header
->size
, size
, "check preoslog sizes - expected %zu, given %zu", size
, header
->size
);
109 T_ASSERT_LT(header
->offset
, header
->size
- sizeof(*header
), "check write offset");
111 lower_buffer
= header
->data
;
112 lower_buffer_size
= header
->offset
+ 1;
113 upper_buffer
= lower_buffer
+ lower_buffer_size
;
114 upper_buffer_size
= header
->size
- lower_buffer_size
- sizeof(*header
);
115 if (header
->wrapped
) {
116 found
= check_for_substrings(upper_buffer
, upper_buffer_size
);
119 found
= found
|| check_for_substrings(lower_buffer
, lower_buffer_size
);
120 T_ASSERT_TRUE(found
, "Verify buffer content");