5 * Copyright (c) 2006 Christoph Pfisterer
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the
20 * * Neither the name of Christoph Pfisterer nor the names of the
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include "refit_call_wrapper.h"
39 #ifdef __MAKEWITH_TIANO
40 //#include "tiano_includes.h"
46 EFI_BLOCK_IO
*BlockIO
= NULL
;
49 // sector I/O functions
52 // Returns size of disk in blocks
53 UINT64
disk_size(VOID
) {
54 return (UINT64
) (BlockIO
->Media
->LastBlock
+ 1);
55 } // UINT64 disk_size()
57 UINTN
read_sector(UINT64 lba
, UINT8
*buffer
)
61 Status
= refit_call5_wrapper(BlockIO
->ReadBlocks
, BlockIO
, BlockIO
->Media
->MediaId
, lba
, 512, buffer
);
62 if (EFI_ERROR(Status
)) {
69 UINTN
write_sector(UINT64 lba
, UINT8
*buffer
)
73 Status
= refit_call5_wrapper(BlockIO
->WriteBlocks
, BlockIO
, BlockIO
->Media
->MediaId
, lba
, 512, buffer
);
74 if (EFI_ERROR(Status
)) {
85 static BOOLEAN
ReadAllKeyStrokes(VOID
)
88 BOOLEAN GotKeyStrokes
;
91 GotKeyStrokes
= FALSE
;
93 Status
= refit_call2_wrapper(ST
->ConIn
->ReadKeyStroke
, ST
->ConIn
, &Key
);
94 if (Status
== EFI_SUCCESS
) {
100 return GotKeyStrokes
;
103 static VOID
PauseForKey(VOID
)
107 Print(L
"\n* Hit any key to continue *");
109 if (ReadAllKeyStrokes()) { // remove buffered key strokes
110 refit_call1_wrapper(BS
->Stall
, 5000000); // 5 seconds delay
111 ReadAllKeyStrokes(); // empty the buffer again
114 refit_call3_wrapper(BS
->WaitForEvent
, 1, &ST
->ConIn
->WaitForKey
, &Index
);
115 ReadAllKeyStrokes(); // empty the buffer to protect the menu
120 UINTN
input_boolean(CHARN
*prompt
, BOOLEAN
*bool_out
)
128 if (ReadAllKeyStrokes()) { // remove buffered key strokes
129 refit_call1_wrapper(BS
->Stall
, 500000); // 0.5 seconds delay
130 ReadAllKeyStrokes(); // empty the buffer again
133 refit_call3_wrapper(BS
->WaitForEvent
, 1, &ST
->ConIn
->WaitForKey
, &Index
);
134 Status
= refit_call2_wrapper(ST
->ConIn
->ReadKeyStroke
, ST
->ConIn
, &Key
);
135 if (EFI_ERROR(Status
))
138 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
150 #ifdef __MAKEWITH_TIANO
152 // EFI_GUID gEfiDxeServicesTableGuid = { 0x05AD34BA, 0x6F02, 0x4214, { 0x95, 0x2E, 0x4D, 0xA0, 0x39, 0x8E, 0x2B, 0xB9 }};
154 // Minimal initialization function
155 static VOID
InitializeLib(IN EFI_HANDLE ImageHandle
, IN EFI_SYSTEM_TABLE
*SystemTable
) {
157 // gImageHandle = ImageHandle;
158 gBS
= SystemTable
->BootServices
;
159 // gRS = SystemTable->RuntimeServices;
160 gRT
= SystemTable
->RuntimeServices
; // Some BDS functions need gRT to be set
162 // InitializeConsoleSim();
165 // EFI_GUID gEfiBlockIoProtocolGuid = { 0x964E5B21, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
167 #define LibLocateHandle gBS->LocateHandleBuffer
168 #define BlockIoProtocol gEfiBlockIoProtocolGuid
172 // Performs a case-insensitive string comparison. This function is necesary
173 // because some EFIs have buggy StriCmp() functions that actually perform
174 // case-sensitive comparisons.
175 // Returns TRUE if strings are identical, FALSE otherwise.
176 static BOOLEAN
MyStriCmp(IN CHAR16
*FirstString
, IN CHAR16
*SecondString
) {
177 if (FirstString
&& SecondString
) {
178 while ((*FirstString
!= L
'\0') && ((*FirstString
& ~0x20) == (*SecondString
& ~0x20))) {
182 return (*FirstString
== *SecondString
);
186 } // BOOLEAN MyStriCmp()
188 // Check firmware vendor; get verification to continue if it's not Apple.
189 // Returns TRUE if Apple firmware or if user assents to use, FALSE otherwise.
190 static BOOLEAN
VerifyGoOn(VOID
) {
194 if (MyStriCmp(L
"Apple", ST
->FirmwareVendor
)) {
195 Print(L
"Your firmware is made by %s.\n", ST
->FirmwareVendor
);
196 Print(L
"Ordinarily, a hybrid MBR (which this program creates) should be used ONLY on\n");
197 Print(L
"Apple Macs that dual-boot with Windows or some other BIOS-mode OS. Are you\n");
198 invalid
= input_boolean(STR("SURE you want to continue? [y/N] "), &GoOn
);
203 } // BOOLEAN VerifyGoOn()
211 efi_main (IN EFI_HANDLE ImageHandle
,
212 IN EFI_SYSTEM_TABLE
*SystemTable
)
218 EFI_HANDLE
*HandleBuffer
;
219 EFI_HANDLE DeviceHandle
;
220 EFI_DEVICE_PATH
*DevicePath
, *NextDevicePath
;
223 InitializeLib(ImageHandle
, SystemTable
);
225 Status
= refit_call5_wrapper(BS
->LocateHandleBuffer
, ByProtocol
, &BlockIoProtocol
, NULL
, &HandleCount
, &HandleBuffer
);
226 if (EFI_ERROR (Status
)) {
227 Status
= EFI_NOT_FOUND
;
234 for (Index
= 0; Index
< HandleCount
; Index
++) {
236 DeviceHandle
= HandleBuffer
[Index
];
239 DevicePath
= DevicePathFromHandle(DeviceHandle
);
241 while (DevicePath
!= NULL
&& !IsDevicePathEndType(DevicePath
)) {
242 NextDevicePath
= NextDevicePathNode(DevicePath
);
244 if (DevicePathType(DevicePath
) == MESSAGING_DEVICE_PATH
&&
245 (DevicePathSubType(DevicePath
) == MSG_USB_DP
||
246 DevicePathSubType(DevicePath
) == MSG_USB_CLASS_DP
||
247 DevicePathSubType(DevicePath
) == MSG_1394_DP
||
248 DevicePathSubType(DevicePath
) == MSG_FIBRECHANNEL_DP
))
249 Usable
= FALSE
; // USB/FireWire/FC device
250 if (DevicePathType(DevicePath
) == MEDIA_DEVICE_PATH
)
251 Usable
= FALSE
; // partition, El Torito entry, legacy BIOS device
253 DevicePath
= NextDevicePath
;
258 Status
= refit_call3_wrapper(BS
->HandleProtocol
, DeviceHandle
, &BlockIoProtocol
, (VOID
**) &BlockIO
);
259 if (EFI_ERROR(Status
)) {
260 // TODO: report error
263 if (BlockIO
->Media
->BlockSize
!= 512)
264 BlockIO
= NULL
; // optical media
271 FreePool (HandleBuffer
);
273 if (BlockIO
== NULL
) {
274 Print(L
"Internal hard disk device not found!\n");
275 return EFI_NOT_FOUND
;
278 SyncStatus
= gptsync();
285 return EFI_NOT_FOUND
;