summaryrefslogtreecommitdiffhomepage
path: root/Kernel/FirmwareKit/EFI/API.hxx
blob: 8e8183d6cf52498b040de6b7d7ba6084c32d7942 (plain)
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
/* -------------------------------------------

	Copyright SoftwareLabs

------------------------------------------- */

#ifndef __EFI_API__
#define __EFI_API__

#include <FirmwareKit/EFI/EFI.hxx>
#include <FirmwareKit/Handover.hxx>
#include <KernelKit/MSDOS.hpp>
#include <KernelKit/PE.hxx>

#ifdef __NEWBOOT__
// forward decl.
class BTextWriter;

#define __BOOTKIT_NO_INCLUDE__ 1

#include <BootKit/BootKit.hxx>
#include <BootKit/Rsrc/NewBootFatal.rsrc>
#include <BootKit/Vendor/Qr.hxx>
#include <Builtins/Toolbox/Toolbox.hxx>
#endif // ifdef __NEWBOOT__

inline EfiSystemTable*	ST = nullptr;
inline EfiBootServices* BS = nullptr;

EXTERN_C void rt_cli();
EXTERN_C void rt_hlt();

namespace EFI
{
	/// @brief Halt and clear interrupts.
	/// @return
	inline Void Stop() noexcept
	{
		while (1)
		{
			rt_hlt();
			rt_cli();
		}
	}

	/**
@brief Exit EFI API to let the OS load correctly.
Bascially frees everything we have in the EFI side.
*/
	inline void ExitBootServices(UInt64 MapKey, EfiHandlePtr ImageHandle) noexcept
	{
		if (!ST)
			return;

		ST->BootServices->ExitBootServices(ImageHandle, MapKey);
	}

	enum
	{
		kPartEPM,
		kPartGPT,
		kPartMBR,
		kPartCnt,
	};

	inline UInt32 Platform() noexcept
	{
		return kPEMachineAMD64;
	}

	/***
	 * @brief Throw an error, stop execution as well.
	 * @param ErrorCode error code to be print.
	 * @param Reason reason to be print.
	 */
	inline void ThrowError(const EfiCharType* ErrorCode,
						   const EfiCharType* Reason) noexcept
	{
#ifdef __DEBUG__
		ST->ConOut->OutputString(ST->ConOut, L"\r*** STOP ***\r");

		ST->ConOut->OutputString(ST->ConOut, L"*** Error: ");
		ST->ConOut->OutputString(ST->ConOut, ErrorCode);

		ST->ConOut->OutputString(ST->ConOut, L", Reason: ");
		ST->ConOut->OutputString(ST->ConOut, Reason);

		ST->ConOut->OutputString(ST->ConOut, L" ***\r");
#endif // ifdef __DEBUG__

#ifdef __NEWBOOT__
		ToolboxInitRsrc();

		ToolboxDrawRsrc(NewBootFatal, NEWBOOTFATAL_HEIGHT, NEWBOOTFATAL_WIDTH,
						(kHandoverHeader->f_GOP.f_Width - NEWBOOTFATAL_WIDTH) / 2,
						(kHandoverHeader->f_GOP.f_Height - NEWBOOTFATAL_HEIGHT) / 2);

		ToolboxClearRsrc();

		/// Show the QR code now.

		constexpr auto ver = 4;
		auto		   ecc = qr::Ecc::H;
		auto		   str = "https://el-mahrouss-logic.com/";
		auto		   len = StrLen("https://el-mahrouss-logic.com/");

		qr::Qr<ver>	   encoder;
		qr::QrDelegate encoderDelegate;

		encoder.encode(str, len, ecc, 0); // Manual mask 0

		/// tell delegate to draw encoded QR.
		encoderDelegate.draw<ver>(encoder, (kHandoverHeader->f_GOP.f_Width - encoder.side_size()) - 20,
								  (kHandoverHeader->f_GOP.f_Height - encoder.side_size()) / 2);

#endif // ifdef __NEWBOOT__

		EFI::Stop();
	}
} // namespace EFI

inline void InitEFI(EfiSystemTable* SystemTable) noexcept
{
	if (!SystemTable)
		return;

	ST = SystemTable;
	BS = ST->BootServices;

	ST->ConOut->ClearScreen(SystemTable->ConOut);
	ST->ConOut->SetAttribute(SystemTable->ConOut, kEFIYellow);

	ST->BootServices->SetWatchdogTimer(0, 0, 0, nullptr);
	ST->ConOut->EnableCursor(ST->ConOut, false);
}

#ifdef __BOOTLOADER__

#include <BootKit/Platform.hxx>

#endif // ifdef __BOOTLOADER__

#define kNewOSSubsystem 17

#endif /* ifndef __EFI_API__ */