void C4Window::RequestUpdate() { // just invoke directly PerformUpdate(); }
bool RunUpdater(std::vector<std::string> args) { std::optional<Options> maybe_opts = ParseCommandLine(args); if (!maybe_opts) { return false; } UI::Init(); Options opts = std::move(*maybe_opts); if (opts.log_file) { log_fp = fopen(opts.log_file.value().c_str(), "w"); if (!log_fp) log_fp = stderr; else atexit(FlushLog); } fprintf(log_fp, "Updating from: %s\n", opts.this_manifest_url.c_str()); fprintf(log_fp, "Updating to: %s\n", opts.next_manifest_url.c_str()); fprintf(log_fp, "Install path: %s\n", opts.install_base_path.c_str()); if (!File::IsDirectory(opts.install_base_path)) { FatalError("Cannot find install base path, or not a directory."); return false; } if (opts.parent_pid) { UI::SetDescription("Waiting for Dolphin to quit..."); fprintf(log_fp, "Waiting for parent PID %d to complete...\n", *opts.parent_pid); auto pid = opts.parent_pid.value(); UI::WaitForPID(static_cast<u32>(pid)); fprintf(log_fp, "Completed! Proceeding with update.\n"); } UI::SetVisible(true); UI::SetDescription("Fetching and parsing manifests..."); Manifest this_manifest, next_manifest; { std::optional<Manifest> maybe_manifest = FetchAndParseManifest(opts.this_manifest_url); if (!maybe_manifest) { FatalError("Could not fetch current manifest. Aborting."); return false; } this_manifest = std::move(*maybe_manifest); maybe_manifest = FetchAndParseManifest(opts.next_manifest_url); if (!maybe_manifest) { FatalError("Could not fetch next manifest. Aborting."); return false; } next_manifest = std::move(*maybe_manifest); } UI::SetDescription("Computing what to do..."); TodoList todo = ComputeActionsToDo(this_manifest, next_manifest); todo.Log(); std::optional<std::string> maybe_temp_dir = FindOrCreateTempDir(opts.install_base_path); if (!maybe_temp_dir) return false; std::string temp_dir = std::move(*maybe_temp_dir); UI::SetDescription("Performing Update..."); bool ok = PerformUpdate(todo, opts.install_base_path, opts.content_store_url, temp_dir); if (!ok) { FatalError("Failed to apply the update."); CleanUpTempDir(temp_dir, todo); return false; } UI::ResetCurrentProgress(); UI::ResetTotalProgress(); UI::SetCurrentMarquee(false); UI::SetTotalMarquee(false); UI::SetCurrentProgress(1, 1); UI::SetTotalProgress(1, 1); UI::SetDescription("Done!"); // Let the user process that we are done. UI::Sleep(1); if (opts.binary_to_restart) { UI::LaunchApplication(opts.binary_to_restart.value()); } UI::Stop(); return true; }
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) { std::optional<Options> maybe_opts = ParseCommandLine(pCmdLine); if (!maybe_opts) return 1; Options opts = std::move(*maybe_opts); if (opts.log_file) { log_fp = _wfopen(UTF8ToUTF16(*opts.log_file).c_str(), L"w"); if (!log_fp) log_fp = stderr; else atexit(FlushLog); } fprintf(log_fp, "Updating from: %s\n", opts.this_manifest_url.c_str()); fprintf(log_fp, "Updating to: %s\n", opts.next_manifest_url.c_str()); fprintf(log_fp, "Install path: %s\n", opts.install_base_path.c_str()); if (!File::IsDirectory(opts.install_base_path)) { fprintf(log_fp, "Cannot find install base path, or not a directory.\n"); return 1; } if (opts.parent_pid) { fprintf(log_fp, "Waiting for parent PID %d to complete...\n", *opts.parent_pid); HANDLE parent_handle = OpenProcess(SYNCHRONIZE, FALSE, *opts.parent_pid); WaitForSingleObject(parent_handle, INFINITE); CloseHandle(parent_handle); fprintf(log_fp, "Completed! Proceeding with update.\n"); } Manifest this_manifest, next_manifest; { std::optional<Manifest> maybe_manifest = FetchAndParseManifest(opts.this_manifest_url); if (!maybe_manifest) { fprintf(log_fp, "Could not fetch current manifest. Aborting.\n"); return 1; } this_manifest = std::move(*maybe_manifest); maybe_manifest = FetchAndParseManifest(opts.next_manifest_url); if (!maybe_manifest) { fprintf(log_fp, "Could not fetch next manifest. Aborting.\n"); return 1; } next_manifest = std::move(*maybe_manifest); } TodoList todo = ComputeActionsToDo(this_manifest, next_manifest); todo.Log(); std::optional<std::string> maybe_temp_dir = FindOrCreateTempDir(opts.install_base_path); if (!maybe_temp_dir) return 1; std::string temp_dir = std::move(*maybe_temp_dir); bool ok = PerformUpdate(todo, opts.install_base_path, opts.content_store_url, temp_dir); if (!ok) fprintf(log_fp, "Failed to apply the update.\n"); CleanUpTempDir(temp_dir, todo); return !ok; }
/** Update System Firmware image. @param[in] SystemFirmwareImage Points to the System Firmware image. @param[in] SystemFirmwareImageSize The length of the System Firmware image in bytes. @param[in] ConfigImage Points to the config file image. @param[in] ConfigImageSize The length of the config file image in bytes. @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. @retval EFI_SUCCESS The System Firmware image is updated. @retval EFI_WRITE_PROTECTED The flash device is read only. **/ EFI_STATUS UpdateImage ( IN VOID *SystemFirmwareImage, IN UINTN SystemFirmwareImageSize, IN VOID *ConfigImage, IN UINTN ConfigImageSize, OUT UINT32 *LastAttemptVersion, OUT UINT32 *LastAttemptStatus ) { EFI_STATUS Status; UPDATE_CONFIG_DATA *ConfigData; UPDATE_CONFIG_DATA *UpdateConfigData; CONFIG_HEADER ConfigHeader; UINTN Index; if (ConfigImage == NULL) { DEBUG((DEBUG_INFO, "PlatformUpdate (NoConfig):")); DEBUG((DEBUG_INFO, " BaseAddress - 0x%x,", 0)); DEBUG((DEBUG_INFO, " Length - 0x%x\n", SystemFirmwareImageSize)); // ASSUME the whole System Firmware include NVRAM region. Status = PerformFlashWrite ( PlatformFirmwareTypeNvRam, 0, FlashAddressTypeRelativeAddress, SystemFirmwareImage, SystemFirmwareImageSize ); if (!EFI_ERROR(Status)) { *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; mNvRamUpdated = TRUE; } else { *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; } return Status; } DEBUG((DEBUG_INFO, "PlatformUpdate (With Config):\n")); ConfigData = NULL; ZeroMem (&ConfigHeader, sizeof(ConfigHeader)); Status = ParseUpdateDataFile ( ConfigImage, ConfigImageSize, &ConfigHeader, &ConfigData ); DEBUG((DEBUG_INFO, "ParseUpdateDataFile - %r\n", Status)); if (EFI_ERROR(Status)) { *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; return EFI_INVALID_PARAMETER; } DEBUG((DEBUG_INFO, "ConfigHeader.NumOfUpdates - 0x%x\n", ConfigHeader.NumOfUpdates)); DEBUG((DEBUG_INFO, "PcdEdkiiSystemFirmwareFileGuid - %g\n", PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid))); Index = 0; UpdateConfigData = ConfigData; while (Index < ConfigHeader.NumOfUpdates) { if (CompareGuid(&UpdateConfigData->FileGuid, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid))) { DEBUG((DEBUG_INFO, "FileGuid - %g (processing)\n", &UpdateConfigData->FileGuid)); Status = PerformUpdate ( SystemFirmwareImage, SystemFirmwareImageSize, UpdateConfigData, LastAttemptVersion, LastAttemptStatus ); // // Shall updates be serialized so that if an update is not successfully completed, // the remaining updates won't be performed. // if (EFI_ERROR (Status)) { break; } } else { DEBUG((DEBUG_INFO, "FileGuid - %g (ignored)\n", &UpdateConfigData->FileGuid)); } Index++; UpdateConfigData++; } return Status; }