37} ANDROID_FASTBOOT_STATE;
39STATIC ANDROID_FASTBOOT_STATE mState = ExpectCmdState;
42STATIC UINT64 mNumDataBytes;
44STATIC UINT64 mBytesReceivedSoFar;
55#define SEND_LITERAL(Str) mTransport->Send ( \
58 &mFatalSendErrorEvent \
60#define MATCH_CMD_LITERAL(Cmd, Buf) !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1)
62#define IS_LOWERCASE_ASCII(Char) (Char >= 'a' && Char <= 'z')
64#define FASTBOOT_STRING_MAX_LENGTH 256
65#define FASTBOOT_COMMAND_MAX_LENGTH 64
73 CHAR8 Response[FASTBOOT_COMMAND_MAX_LENGTH + 1] =
"OKAY";
77 if (!
AsciiStrnCmp (
"version", CmdArg,
sizeof (
"version") - 1)) {
78 SEND_LITERAL (
"OKAY" ANDROID_FASTBOOT_VERSION);
81 Status = mPlatform->GetVar (CmdArg, Response + 4);
82 if (EFI_ERROR (Status)) {
83 SEND_LITERAL (
"FAILSomething went wrong when looking up the variable");
85 mTransport->Send (
AsciiStrLen (Response), Response, &mFatalSendErrorEvent);
93 IN CHAR8 *NumBytesString
97 CHAR16 OutputString[FASTBOOT_STRING_MAX_LENGTH];
104 if (mDataBuffer !=
NULL) {
111 if (mNumDataBytes == 0) {
112 mTextOut->OutputString (mTextOut, L
"ERROR: Fail to get the number of bytes to download.\r\n");
113 SEND_LITERAL (
"FAILFailed to get the number of bytes to download");
117 UnicodeSPrint (OutputString,
sizeof (OutputString), L
"Downloading %d bytes\r\n", mNumDataBytes);
118 mTextOut->OutputString (mTextOut, OutputString);
121 if (mDataBuffer ==
NULL) {
122 SEND_LITERAL (
"FAILNot enough memory");
124 ZeroMem (Response,
sizeof Response);
129 (UINT32)mNumDataBytes
131 mTransport->Send (
sizeof Response - 1, Response, &mFatalSendErrorEvent);
133 mState = ExpectDataState;
134 mBytesReceivedSoFar = 0;
141 IN CHAR8 *PartitionName
145 CHAR16 OutputString[FASTBOOT_STRING_MAX_LENGTH];
148 UnicodeSPrint (OutputString,
sizeof (OutputString), L
"Flashing partition %a\r\n", PartitionName);
149 mTextOut->OutputString (mTextOut, OutputString);
151 if (mDataBuffer ==
NULL) {
153 SEND_LITERAL (
"FAILNo data to flash");
157 Status = mPlatform->FlashPartition (
162 if (Status == EFI_NOT_FOUND) {
163 SEND_LITERAL (
"FAILNo such partition.");
164 mTextOut->OutputString (mTextOut, L
"No such partition.\r\n");
165 }
else if (EFI_ERROR (Status)) {
166 SEND_LITERAL (
"FAILError flashing partition.");
167 mTextOut->OutputString (mTextOut, L
"Error flashing partition.\r\n");
168 DEBUG ((DEBUG_ERROR,
"Couldn't flash image: %r\n", Status));
170 mTextOut->OutputString (mTextOut, L
"Done.\r\n");
171 SEND_LITERAL (
"OKAY");
178 IN CHAR8 *PartitionName
182 CHAR16 OutputString[FASTBOOT_STRING_MAX_LENGTH];
185 UnicodeSPrint (OutputString,
sizeof (OutputString), L
"Erasing partition %a\r\n", PartitionName);
186 mTextOut->OutputString (mTextOut, OutputString);
188 Status = mPlatform->ErasePartition (PartitionName);
189 if (EFI_ERROR (Status)) {
190 SEND_LITERAL (
"FAILCheck device console.");
191 DEBUG ((DEBUG_ERROR,
"Couldn't erase image: %r\n", Status));
193 SEND_LITERAL (
"OKAY");
205 mTextOut->OutputString (mTextOut, L
"Booting downloaded image\r\n");
207 if (mDataBuffer ==
NULL) {
209 SEND_LITERAL (
"FAILNo image in memory");
215 SEND_LITERAL (
"OKAY");
217 Status = BootAndroidBootImg (mNumDataBytes, mDataBuffer);
218 if (EFI_ERROR (Status)) {
219 DEBUG ((DEBUG_ERROR,
"Failed to boot downloaded image: %r\n", Status));
233 Status = mPlatform->DoOemCommand (Command);
234 if (Status == EFI_NOT_FOUND) {
235 SEND_LITERAL (
"FAILOEM Command not recognised.");
236 }
else if (Status == EFI_DEVICE_ERROR) {
237 SEND_LITERAL (
"FAILError while executing command");
238 }
else if (EFI_ERROR (Status)) {
239 SEND_LITERAL (
"FAIL");
241 SEND_LITERAL (
"OKAY");
252 CHAR8 Command[FASTBOOT_COMMAND_MAX_LENGTH + 1];
255 if (Size > FASTBOOT_COMMAND_MAX_LENGTH) {
256 SEND_LITERAL (
"FAILCommand too large");
264 if (MATCH_CMD_LITERAL (
"getvar", Command)) {
265 HandleGetVar (Command +
sizeof (
"getvar"));
266 }
else if (MATCH_CMD_LITERAL (
"download", Command)) {
267 HandleDownload (Command +
sizeof (
"download"));
268 }
else if (MATCH_CMD_LITERAL (
"verify", Command)) {
269 SEND_LITERAL (
"FAILNot supported");
270 }
else if (MATCH_CMD_LITERAL (
"flash", Command)) {
271 HandleFlash (Command +
sizeof (
"flash"));
272 }
else if (MATCH_CMD_LITERAL (
"erase", Command)) {
273 HandleErase (Command +
sizeof (
"erase"));
274 }
else if (MATCH_CMD_LITERAL (
"boot", Command)) {
276 }
else if (MATCH_CMD_LITERAL (
"continue", Command)) {
277 SEND_LITERAL (
"OKAY");
278 mTextOut->OutputString (mTextOut, L
"Received 'continue' command. Exiting Fastboot mode\r\n");
280 gBS->SignalEvent (mFinishedEvent);
281 }
else if (MATCH_CMD_LITERAL (
"reboot", Command)) {
282 if (MATCH_CMD_LITERAL (
"reboot-booloader", Command)) {
288 SEND_LITERAL (
"INFOreboot-bootloader not supported, rebooting normally.");
291 SEND_LITERAL (
"OKAY");
295 DEBUG ((DEBUG_ERROR,
"Fastboot: gRT->ResetSystem didn't work\n"));
296 }
else if (MATCH_CMD_LITERAL (
"powerdown", Command)) {
297 SEND_LITERAL (
"OKAY");
301 DEBUG ((DEBUG_ERROR,
"Fastboot: gRT->ResetSystem didn't work\n"));
302 }
else if (MATCH_CMD_LITERAL (
"oem", Command)) {
305 HandleOemCommand (Command +
sizeof (
"oem"));
306 }
else if (IS_LOWERCASE_ASCII (Command[0])) {
312 SEND_LITERAL (
"FAILCommand not recognised. Check Fastboot version.");
314 HandleOemCommand (Command);
325 UINT32 RemainingBytes = mNumDataBytes - mBytesReceivedSoFar;
326 CHAR16 OutputString[FASTBOOT_STRING_MAX_LENGTH];
330 if (Size > RemainingBytes) {
331 Size = RemainingBytes;
334 CopyMem (&mDataBuffer[mBytesReceivedSoFar], Data, Size);
336 mBytesReceivedSoFar += Size;
340 if (((Count++ % 32) == 0) || (Size == RemainingBytes)) {
344 sizeof (OutputString),
345 L
"\r%8d / %8d bytes downloaded (%d%%)",
348 (mBytesReceivedSoFar * 100) / mNumDataBytes
350 mTextOut->OutputString (mTextOut, OutputString);
353 if (mBytesReceivedSoFar == mNumDataBytes) {
356 mTextOut->OutputString (mTextOut, L
"\r\n");
357 SEND_LITERAL (
"OKAY");
358 mState = ExpectCmdState;
380 Status = mTransport->Receive (&Size, &Data);
381 if (!EFI_ERROR (Status)) {
382 if (mState == ExpectCmdState) {
383 AcceptCmd (Size, (CHAR8 *)Data);
384 }
else if (mState == ExpectDataState) {
385 AcceptData (Size, Data);
392 }
while (!EFI_ERROR (Status));
395 if (Status != EFI_NOT_READY) {
396 ASSERT (Status == EFI_DEVICE_ERROR);
399 mTextOut->OutputString (mTextOut, L
"\r\nFatal error receiving data. Exiting.\r\n");
400 gBS->SignalEvent (mFinishedEvent);
414 mTextOut->OutputString (mTextOut, L
"Fatal error sending command response. Exiting.\r\n");
415 gBS->SignalEvent (mFinishedEvent);
420FastbootAppEntryPoint (
434 Status =
gBS->LocateProtocol (
435 &gAndroidFastbootTransportProtocolGuid,
439 if (EFI_ERROR (Status)) {
440 DEBUG ((DEBUG_ERROR,
"Fastboot: Couldn't open Fastboot Transport Protocol: %r\n", Status));
444 Status =
gBS->LocateProtocol (&gAndroidFastbootPlatformProtocolGuid,
NULL, (VOID **)&mPlatform);
445 if (EFI_ERROR (Status)) {
446 DEBUG ((DEBUG_ERROR,
"Fastboot: Couldn't open Fastboot Platform Protocol: %r\n", Status));
450 Status = mPlatform->Init ();
451 if (EFI_ERROR (Status)) {
452 DEBUG ((DEBUG_ERROR,
"Fastboot: Couldn't initialise Fastboot Platform Protocol: %r\n", Status));
456 Status =
gBS->LocateProtocol (&gEfiSimpleTextOutProtocolGuid,
NULL, (VOID **)&mTextOut);
457 if (EFI_ERROR (Status)) {
460 "Fastboot: Couldn't open Text Output Protocol: %r\n",
466 Status =
gBS->LocateProtocol (&gEfiSimpleTextInProtocolGuid,
NULL, (VOID **)&TextIn);
467 if (EFI_ERROR (Status)) {
468 DEBUG ((DEBUG_ERROR,
"Fastboot: Couldn't open Text Input Protocol: %r\n", Status));
473 Status =
gBS->SetWatchdogTimer (0, 0x10000, 0,
NULL);
474 if (EFI_ERROR (Status)) {
475 DEBUG ((DEBUG_ERROR,
"Fastboot: Couldn't disable watchdog timer: %r\n", Status));
479 Status =
gBS->CreateEvent (
489 Status =
gBS->CreateEvent (0, TPL_CALLBACK,
NULL,
NULL, &mFinishedEvent);
494 Status =
gBS->CreateEvent (
499 &mFatalSendErrorEvent
504 Status = mTransport->Start (
507 if (EFI_ERROR (Status)) {
508 DEBUG ((DEBUG_ERROR,
"Fastboot: Couldn't start transport: %r\n", Status));
513 mTextOut->OutputString (
515 L
"Android Fastboot mode - version " ANDROID_FASTBOOT_VERSION
". Press RETURN or SPACE key to quit.\r\n"
519 WaitEventArray[0] = mFinishedEvent;
520 WaitEventArray[1] = TextIn->WaitForKey;
522 gBS->WaitForEvent (2, WaitEventArray, &EventIndex);
523 Status = TextIn->ReadKeyStroke (
gST->
ConIn, &Key);
524 if (Key.ScanCode == SCAN_NULL) {
525 if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN) ||
526 (Key.UnicodeChar == L
' '))
534 if (EFI_ERROR (Status)) {
535 DEBUG ((DEBUG_ERROR,
"Warning: Fastboot Transport Stop: %r\n", Status));
538 mPlatform->UnInit ();
RETURN_STATUS EFIAPI AsciiStrnCpyS(OUT CHAR8 *Destination, IN UINTN DestMax, IN CONST CHAR8 *Source, IN UINTN Length)
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
INTN EFIAPI AsciiStrnCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString, IN UINTN Length)
UINT64 EFIAPI AsciiStrHexToUint64(IN CONST CHAR8 *String)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID EFIAPI FreePool(IN VOID *Buffer)
UINTN EFIAPI UnicodeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
UINTN EFIAPI AsciiSPrint(OUT CHAR8 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR8 *FormatString,...)
EFI_RUNTIME_SERVICES * gRT
#define ASSERT_EFI_ERROR(StatusParameter)
#define DEBUG(Expression)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
EFI_SIMPLE_TEXT_INPUT_PROTOCOL * ConIn