-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathboot2target.c
More file actions
157 lines (133 loc) · 3.65 KB
/
boot2target.c
File metadata and controls
157 lines (133 loc) · 3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* SPDX-License-Identifier: MIT */
#include <boot2target.h>
EFI_HANDLE gImageHandle;
EFI_SYSTEM_TABLE *gST;
EFI_BOOT_SERVICES *gBS;
static NORETURN
VOID
Reboot(VOID)
{
while (1)
{
gST->RuntimeServices->ResetSystem(
EfiResetCold,
EFI_SUCCESS,
0,
NULL);
}
}
static NORETURN
VOID
Halt(VOID)
{
while (1)
{
gST->RuntimeServices->ResetSystem(
EfiResetShutdown,
EFI_SUCCESS,
0,
NULL);
}
}
EFI_STATUS
EFIAPI
EfiMain(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable)
{
EFI_STATUS Status;
APPLE_SMC_IO_PROTOCOL *SmcIo = NULL;
BOOLEAN TargetDisplayEnabled = FALSE;
BOOLEAN CableConnected;
gST = SystemTable;
gBS = SystemTable->BootServices;
gImageHandle = ImageHandle;
/* Disable watchdog timer so we don't auto-reboot after 5 minutes */
gBS->SetWatchdogTimer(0, 0, 0, NULL);
/* Initialize console */
if (!InitializeConsole())
{
// Reboot without question if this fails for some reason
Reboot();
}
/* Find Apple SMC I/O protocol */
Status = gBS->LocateProtocol(
&gAppleSmcIoProtocolGuid,
NULL,
(VOID **) &SmcIo
);
if (EFI_ERROR(Status))
{
printf("Cannot find SMC I/O protocol!\n");
goto Fail;
}
printf("Boot2TargetDisplay %d.%d", VERSION_MAJOR, VERSION_MINOR);
if (VERSION_PATCH != 0) printf(".%d", VERSION_PATCH);
printf("\n");
printf("Copyright 2026 Sylas Hollander.\n");
printf("Waiting for cable connection...\n");
/* FIXME: Use timers */
while (1)
{
Status = TdmIsCableConnected(SmcIo, &CableConnected);
if (EFI_ERROR(Status))
{
printf("Unsupported device! Please note that Thunderbolt iMacs are not currently supported.\n");
break;
}
if (CableConnected)
{
if (!TargetDisplayEnabled)
{
Status = TdmToggle(SmcIo, TRUE);
if (EFI_ERROR(Status))
{
printf("Cannot enable Target Display Mode!\n");
break;
}
gBS->Stall(250000);
Status = TdmResetLcd(SmcIo);
if (EFI_ERROR(Status))
{
printf("Cannot reset display!\n");
break;
}
TargetDisplayEnabled = TRUE;
}
}
else
{
/* Cable no longer connected */
if (TargetDisplayEnabled)
{
/* This code doesn't seem to reset the screen properly, might be impossible while in EFI */
#if 0
gBS->Stall(1000000);
Status = TdmToggle(SmcIo, FALSE);
if (EFI_ERROR(Status))
{
printf("Cannot disable Target Display Mode!\n");
break;
}
gBS->Stall(500000);
Status = TdmResetLcd(SmcIo);
if (EFI_ERROR(Status))
{
printf("Cannot reset display!\n");
break;
}
#endif
TargetDisplayEnabled = FALSE;
}
}
gBS->Stall(500000);
}
/* We broke out of the loop, error out */
Fail:
ConsChangeBgColor(COLOR_BLACK);
ConsChangeFgColor(COLOR_YELLOW);
printf("Something went wrong (see above)\n");
printf("Shutting down in 15 seconds...\n");
gBS->Stall(15000000);
Halt();
}