
/*++
Copyright (c) 2018 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:

FwUpdLclApp.c

Abstract:

FW Update Local Sample Code demonstrating usage of FW Update Library

--*/

#include <stdio.h>
#include <stdint.h>
#include <windows.h>

#include "fwudef.h"
#include "fwupdatelib.h"

#define HECI1_CSE_GS1_PHASE_FWUPDATE    7

#define CMD_LINE_STATUS_UPDATE_1        0
#define CMD_LINE_STATUS_UPDATE_2        1
#define CMD_LINE_STATUS_UPDATE_3        2
#define CMD_LINE_STATUS_UPDATE_4        3

// Info Strings 
#define ID_INFO_DOT     "."
#define ID_INFO_2       "\nTrying to receive update status..."
#define ID_INFO_3       "Communication Mode: MEI\n"
#define ID_INFO_16      "Maximum Retry limit reached. Please reboot to try again\n"

// Error Strings 
#define ID_ERROR_2      "\nError %d: Firmware update not initiated due to invalid hostname specified\n"
#define ID_ERROR_3      "\nError %d: Firmware update process or firmware update tool failed due to insufficient memory\n"
#define ID_ERROR_4      "\nError %d: Update operation timed-out; cannot determine if the operation succeeded\n"
#define ID_ERROR_5      "\nError %d: Cannot receive the current version from the firmware after update\n"
#define ID_ERROR_6      "\nError %d: Update finished but version mismatch after the update\n"
#define ID_ERROR_7      "\nError %d: Firmware update not initiated due to an invalid FW image \n"
#define ID_ERROR_8      "\nError %d: Firmware update not initiated due to integrity failure or invalid FW image"
#define ID_ERROR_9      "\nError %d: Sku capabilities bits are different between the Update Image and the Flash Image.\n"
#define ID_ERROR_10     "\nError %d: Major version number of Update Image is not the same as major version number of Flash Image.\n"
#define ID_ERROR_11     "\nError %d: Firmware update failed due to authentication failure\n"
#define ID_ERROR_12     "\nError %d: Firmware update failed due to insufficient memory\n"
#define ID_ERROR_13     "\nError %d: Firmware update iAMT communication failed, Failed to find certificate '%s' in certificate store\n"
#define ID_ERROR_14     "\nError %d: Firmware update iAMT communication failed, Failed to set HTTP certificate options (%d): %s\n"
#define ID_ERROR_15     "\nError %d: Firmware update iAMT communication failed, Failed to find certificate names\n"
#define ID_ERROR_16     "\nError %d: Firmware update iAMT communication failed, Failed to open system certificate store (%d): %s\n"
#define ID_ERROR_17     "\nError %d: Firmware update tool failed to connect iAMT through LMS, due to a HTTP operation failure,\nPlease verify the inputs (host, user, password, certificate, work mode etc).\n"

#define ID_ERROR_18     "\nError %d: Invalid usage\n"
#define ID_ERROR_18B    "\nError %d: Invalid usage, -allowsv switch required to update the same version firmware\n"
#define ID_ERROR_19     "\nError %d: Failed to receive last update status from the firmware\n"
#define ID_ERROR_20     "\nError %d: Firmware Update operation not initiated because a firmware update is already in progress\n"
#define ID_ERROR_21     "\nError %d: Invalid UUID provided with the OEMID switch\n"
#define ID_ERROR_22     "\nError %d: OEM ID verification failed.\n"
#define ID_ERROR_24     "\nError %d: Firmware update tool failed to get the firmware parameters\n"

#define ID_ERROR_25     "\nError %d: Firmware update failed due to an internal error\n"
#define ID_ERROR_25A    "\nError %d: Firmware update failed due to an internal error\nFirmware returns SAL notification error, Please try after ME-reset or re-flashing the ME image.\n"
#define ID_ERROR_25B    "\nError %d: Firmware update failed due to an internal error\nFirmware returns Audit policy error, Please try after ME-reset or re-flashing the ME image.\n"
#define ID_ERROR_25C    "\nError %d: Firmware update failed due to an internal error\nThe total size of the backup partitions is bigger than NFTP size. Can happen in Consumer, when not setting fixed partitions sizes in build.\n"
#define ID_ERROR_25D    "\nError %d: Firmware update failed due to an internal error\nFirmware failed  on image version history check.\n"
#define ID_ERROR_25E    "\nError %d: Firmware update failed due to an internal error\nWrite file failed: error occurred in write() or number of bytes written is not the same as file length.\n"
#define ID_ERROR_25F    "\nError %d: Firmware update failed due to an internal error\nRead file failed: error occurred in read() or number of bytes read is not the same as file length.\n"
#define ID_ERROR_25G    "\nError %d: Firmware update failed due to an internal error\nFirmware failed with delete file issue.\n"
#define ID_ERROR_25H    "\nError %d: Firmware update failed due to an internal error\nFirmware returns invalid flash code partition.\n"
#define ID_ERROR_25I    "\nError %d: Firmware update failed due to an internal error\nNFTP is corrupted, CSE is in Recovery Mode.\n"
#define ID_ERROR_25J    "\nError %d: Firmware update failed due to an internal error\nFirmware returns invalid image length.\n"
#define ID_ERROR_25K    "\nError %d: Firmware update failed due to an internal error\nFirmware returns invalid GLUT.\n"
#define ID_ERROR_25L    "\nError %d: Firmware update failed due to an internal error\nFirmware Update client is not ready to perform an update.\n"


#define ID_ERROR_26     "\nError %d: Unsupported Operating System\n"
#define ID_ERROR_27     "\nError %d: No Firmware update is happening\n"
#define ID_ERROR_28     "\nError %d: Unknown or Unsupported Platform\n"
#define ID_ERROR_29     "\nError %d: FW Update is disabled. MEBX has options to disable / enable / require ME password for FW Update.\n"
#define ID_ERROR_30     "\nError %d: Firmware update cannot be initiated because Secure FW update is disabled\n"
#define ID_ERROR_31     "\nError %d: Firmware update not initiated due to an invalid FW image header\n"
#define ID_ERROR_32     "\nError %d: Firmware update not initiated due to file [%s] open or read failure\n"
#define ID_ERROR_33     "\nError %d: Firmware update cannot be initiated because the OEM ID given for FW Update did not match the OEM ID in the FW.\n"
#define ID_ERROR_34     "\nError %d: Firmware update not initiated due to file open or read failure\n"
#define ID_ERROR_35     "\nError %d: Firmware update iAMT communication failed, HTTP request failed: Certificate rejected\n"
#define ID_ERROR_36     "\nError %d: This version of the Intel (R) FW Update Tool is not compatible with the current platform.\n"
#define ID_ERROR_36A    "\nError %d: Buffer too small\n"
#define ID_ERROR_37     "\nError %d: Fail to load MEI device driver (PCI access for Windows)\nAbove error is often caused by one of below reasons:\nAdministrator privilege needed for running the tool\nME is in an error state causing MEI driver fail\nMEI driver is not installed\n"
#define ID_ERROR_38     "\nError %d: Platform did not respond to update request.\n"
#define ID_ERROR_39     "\nError %d: Intel (R) ME Interface : Unsupported message type\n"
#define ID_ERROR_40     "\nError %d: Firmware update not initiated. Num of bytes to read/write/erase is bigger than partition size\n"
#define ID_ERROR_41     "\nError %d: Firmware update not initiated due to an unavailable global buffer\n"
#define ID_ERROR_44     "\nError %d: Firmware update not initiated due to invalid firmware parameters\n"
#define ID_ERROR_46     "\nError %d: Firmware update iAMT communication failed, WSMAN not supported\n"
#define ID_ERROR_51     "\nError %d: PLEASE REBOOT YOUR SYSTEM. Firmware update cannot be initiated without a reboot.\n"
#define ID_ERROR_52     "\nError %d: An internal error to the AMT device has occurred.\n"
#define ID_ERROR_53     "\nError %d: AMT Status is not ready.\n"
#define ID_ERROR_54     "\nError %d: Invalid AMT Mode.\n"
#define ID_ERROR_55     "\nError %d: Encountered error writing to file.\n"
#define ID_ERROR_56     "\nError %d: Display FW Version failed.\n"
#define ID_ERROR_57     "\nError %d: The image provided is not supported by the platform.\n"
#define ID_ERROR_57A    "\nError %d: This platform does not allow downgrade/upgrade with the file provided.\n"
#define ID_ERROR_58     "\nError %d: Internal Error.\n"
#define ID_ERROR_59     "\nError %d: Update downgrade vetoed.\n"
#define ID_ERROR_60     "\nError %d: Firmware write file failure.\n"
#define ID_ERROR_61     "\nError %d: Firmware read file failure.\n"
#define ID_ERROR_62     "\nError %d: Firmware delete file failure.\n"
#define ID_ERROR_63     "\nError %d: Sanity check in erase/write of partitions. Error might have happened when size of partition is not 4K aligned.\n"
#define ID_ERROR_64     "\nError %d: Downgrade NOT allowed, data mismatched.\n"
#define ID_ERROR_65     "\nError %d: The password given for FW Update did not match the correct password (the password is the ME password set in MEBX).\n"
#define ID_ERROR_66     "\nError %d: The number of attempts to provide password for FW Update exceeds the number of allowed attempts. (3 attempts allowed). (Restart will reset the number of attempts).\n"
#define ID_ERROR_67     "\nError %d: Password Not provided when required.\n"
#define ID_ERROR_68     "\nError %d: Polling for FW Update Failed.\n"
#define ID_ERROR_69     "\nError %d: FW Update Failed.\n"
#define ID_ERROR_70     "\nError %d: Intel (R) ME Interface : Cannot locate ME device driver; unable to determine if the operation succeeded.\n"
#define ID_ERROR_71     "\nError %d: Intel (R) ME Interface : Lost communication with platform during update; unable to determine if the update completed.\n"
#define ID_ERROR_72     "\nError %d: The partition provided is not supported by the platform. Please verify the update image used.\n"
#define ID_ERROR_73     "\nError %d: Firmware is in recovery mode. Please update only using the previously attempted version.\n"
#define ID_ERROR_74     "\nError %d: Invalid Partition ID. Use a Partition ID which is possible to do Partial FW Update on.\n"
#define ID_ERROR_75     "\nError %d: FW update/downgrade is not allowed to the supplied FW image.\n"
#define ID_ERROR_76     "\nError %d: Update to Image with lower SVN is not allowed.\n"
#define ID_ERROR_77     "\nError %d: File already exists.\n"
#define ID_ERROR_78     "\nError %d: Invalid File.\n"
#define ID_ERROR_79     "\nError %d: Restore Point Image Failure. Reboot may be required. \n"
#define ID_ERROR_80     "\nError %d: Get Partition Attribute Failure.\n"
#define ID_ERROR_81     "\nError %d: Get Update Info Status Failure.\n"
#define ID_ERROR_82     "\nError %d: Buffer Copy Failure.\n"
#define ID_ERROR_83     "\nError %d: Invalid pointer.\n"
#define ID_ERROR_84     "\nError %d: UPV version is mismatched.\n"
#define ID_ERROR_85     "\nError %d: Partial update is allowed only to the expected instance ID of an IUP. The Update Image contains IUP with instance ID that is not the currently expected one by the FW. To update LOCL, please use The Intel Management and Security Status (IMSS) tool. \n"
#define ID_ERROR_86     "\nError %d: FW info not available. \n"
#define ID_ERROR_87     "\nError %d: Partial Update is not allowed, because CSE is in Recovery Mode.\n"
#define ID_ERROR_88     "\nError %d: Partial Update of an IUP was requested, but this IUP doesn't exist in the Flash Image.\n"
#define ID_ERROR_89     "\nError %d: Update to Restore Point Image: comparing the hash of the image to the saved hashes of last 10 Restore Point Images that were created previously, did not find a match. This means that the image is not a Restore Point Image.\n"
#define ID_ERROR_90     "\nError %d: Restore point is valid but not the latest. \n"
#define ID_ERROR_91     "\nError %d: Get Restore Point Image is not allowed, because FW Update is in progress. (The regular FW Update will continue). \n"
#define ID_ERROR_92     "\nError %d: Update to Image with lower VCN is not allowed. \n"
#define ID_ERROR_93     "\nError %d: SVN invalid: SVN larger than 254 is not allowed. \n"
#define ID_ERROR_94     "\nError %d: PSVN partition is full, so cannot update to higher SVN. \n"
#define ID_ERROR_95     "\nError %d: Restore Point Image was requested, but it is not allowed because CSE is in Recovery Mode. \n"
#define ID_ERROR_96     "\nError %d: Rejested by update policy. \n"
#define ID_ERROR_97     "\nError %d: Rejected, incompatible tool usage. \n"
#define ID_ERROR_98     "\nError %d: Rejected, crosspoint update not allowed. \n"
#define ID_ERROR_99     "\nError %d: Rejected, crosshotfix update not allowed. \n"
#define ID_ERROR_100    "\nError %d: Rejected, current fw is not eligible for update. \n"
#define ID_ERROR_101    "\nError %d: Rejected, wrong update operation. \n"
#define ID_ERROR_102    "\nError %d: Rejected, wrong update image found. \n"
#define ID_ERROR_103    "\nError %d: Rejected, IFR update not allowed. \n"
#define ID_ERROR_104    "\nError %d: Failure occurred during rollback. \n"
#define ID_ERROR_105    "\nError %d: Restore point operation failed. \n"
#define ID_ERROR_106    "\nError %d: Invalid message length. \n"
#define ID_ERROR_107    "\nError %d: Get blist error. \n"
#define ID_ERROR_108    "\nError %d: Host reset is required after the last FW Update operation. \n"
#define ID_ERROR_109    "\nError %d: Unknown error code. \n"
#define ID_ERROR_110    "\nError %d: Failed to detect power source. \n"
#define ID_ERROR_111    "\nError %d: Display Partition Version failed. \n"
#define ID_ERROR_112    "\nError %d: Binary is not present. \n"
#define ID_ERROR_113    "\nError %d: Request and Reply messages' size mismatch. \n"
#define ID_ERROR_114    "\nError %d: Unsupported Platform: slim SKU is not supported\n"

#define ID_ERROR_115    "\nError %d: Restore Point Image was requested, but there was Full/Partial FW Update before without Restart after it. \n"
#define ID_ERROR_116    "\nError %d: Update to incompatible PMC: The PMC instance ID is different, which may be due to H/LP SKU incompatibility.\n"
#define ID_ERROR_117    "\nError %d: Update to incompatible H/LP SKU image. \n"

#define ID_ERROR_118    "\nError %d: Failed to communicate with CSME.\nThis tool must be run from a privileged account (administrator/root).\n"
#define ID_ERROR_119    "\nError %d: Restore Point Image was requested, but there was Full/Partial FW Update before without Restart after it.\n"
#define ID_ERROR_120    "\nError %d: Update to incompatible PMC: The instance ID is different, which means H/LP incompatibility between the Update Image and the Flash Image.\n"
#define ID_ERROR_121    "\nError %d: Update Image length is bigger than the expected size of the image according to its size in the flash. For example: Error on updating from Consumer to Corporate.\n"
#define ID_ERROR_122    "\nError %d: Manifest size in Update Image is bigger than 8KB, or exceeds the Update Image size.\n"
#define ID_ERROR_123    "\nError %d: Failed to open loader (DEV_FD_LDR_VERIFY_MAN) to verify manifest. \n"
#define ID_ERROR_124    "\nError %d: Failed to open loader (DEV_FD_LDR_VERIFY_MAN) to install / uninstall keys. \n" 
#define ID_ERROR_125    "\nError %d: Failed to verify signature of OEM or RoT key manifests.\n"
#define ID_ERROR_126    "\nError %d: ldr_uninstall_keys() failed - uninstall keys for OEM partitions (ISHC/IUNP). \n"
#define ID_ERROR_127    "\nError %d: Failed to open loader (DEV_FD_LDR_INSTALL) to install pre-update module. \n"
#define ID_ERROR_128    "\nError %d: ldr_install_modules() failed - install pre-update module. \n"
#define ID_ERROR_129    "\nError %d: Failed to create dir or files for preupdate module (permissions, quota). \n"
#define ID_ERROR_130    "\nError %d: spawn() of pre-update module failed - might be permissions problem. \n"
#define ID_ERROR_131    "\nError %d: waitpid() to pre-update module failed. \n"
#define ID_ERROR_132    "\nError %d: Pre-Update module process returned error exit code after it was run. \n"
#define ID_ERROR_133    "\nError %d: Call to sku_mgr functions failed. \n"
#define ID_ERROR_134    "\nError %d: Call to cfgmgr functions failed. cfgmgr_get_rule(), cfgmgr_set_rule(). \n"
#define ID_ERROR_135    "\nError %d: Manifest not found in partition (in Update or Flash Image). \n"
#define ID_ERROR_136    "\nError %d: Crypto operation (calculating hash of partition) failed. \n"
#define ID_ERROR_137    "\nError %d: Loader failed to verify manifest signature of FTPR. Production vs. Pre-Production. \n"
#define ID_ERROR_138    "\nError %d: Loader failed to verify manifest signature of NFTP. \n"
#define ID_ERROR_139    "\nError %d: Loader failed to verify manifest signature of IDLM. \n"
#define ID_ERROR_140    "\nError %d: Loader failed to verify manifest signature of RBE. \n"
#define ID_ERROR_141    "\nError %d: Loader failed to verify manifest signature of PMC. \n"
#define ID_ERROR_142    "\nError %d: Loader failed to verify manifest signature of OEM KM. \n"
#define ID_ERROR_143    "\nError %d: Loader failed to verify manifest signature of WCOD. \n"
#define ID_ERROR_144    "\nError %d: Loader failed to verify manifest signature of LOCL. \n"
#define ID_ERROR_145    "\nError %d: Loader failed to verify manifest signature of PAVP. \n"
#define ID_ERROR_146    "\nError %d: Loader failed to verify manifest signature of IOMP. \n"
#define ID_ERROR_147    "\nError %d: Loader failed to verify manifest signature of MGPP. \n"
#define ID_ERROR_148    "\nError %d: Loader failed to verify manifest signature of TBTP. \n"
#define ID_ERROR_149    "\nError %d: Loader failed to verify manifest signature of ISHC. \n"
#define ID_ERROR_150    "\nError %d: Loader failed to verify manifest signature of IUNIT. \n"
#define ID_ERROR_151    "\nError %d: Loader failed to verify manifest signature of Pre-Update Module. \n"
#define ID_ERROR_152    "\nError %d: Some manifest extension is missing in FTPR. \n"
#define ID_ERROR_153    "\nError %d: Some manifest extension is missing in NFTP. \n"
#define ID_ERROR_154    "\nError %d: Some manifest extension is missing in IDLM. \n"
#define ID_ERROR_155    "\nError %d: Some manifest extension is missing in RBE. \n"
#define ID_ERROR_156    "\nError %d: Some manifest extension is missing in PMC. Wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_157    "\nError %d: Some manifest extension is missing in OEM KM. Wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_158    "\nError %d: Some manifest extension is missing in WCOD. \n"
#define ID_ERROR_159    "\nError %d: Some manifest extension is missing in LOCL. \n"
#define ID_ERROR_160    "\nError %d: Some manifest extension is missing in PAVP. Wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_161    "\nError %d: Some manifest extension is missing in IOMP. Wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_162    "\nError %d: Some manifest extension is missing in MGPP. Wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_163    "\nError %d: Some manifest extension is missing in TBTP. Wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_164    "\nError %d: Some manifest extension is missing in ISHC. Wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_165    "\nError %d: Some manifest extension is missing in IUNIT. Wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_166    "\nError %d: Some manifest extension is missing in Pre-Update Module. \n"
#define ID_ERROR_167    "\nError %d: FTPR partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_168    "\nError %d: NFTP partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_169    "\nError %d: DLMP partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_170    "\nError %d: RBEP partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_171    "\nError %d: PMCP partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_172    "\nError %d: OEMP partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_173    "\nError %d: WCOD partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_174    "\nError %d: LOCL partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_175    "\nError %d: PAVP partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_176    "\nError %d: IOMP partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_177    "\nError %d: MGPP partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_178    "\nError %d: TBTP partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_179    "\nError %d: ISHC partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_180    "\nError %d: IUNP partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_181    "\nError %d: UPDT partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition. \n"
#define ID_ERROR_182    "\nError %d: The size of an Update partition size is bigger than the size of the Flash partition.\n"
#define ID_ERROR_183    "\nError %d: Location of partition to backup is not inside NFTP.\n"
#define ID_ERROR_184    "\nError %d: The number of IUPs in the Update/Flash Image is bigger than MAX_IUPS.\n"
#define ID_ERROR_185    "\nError %d: Partition name inside IUPs list (in FTPR manifest extension) is not IUP.\n"
#define ID_ERROR_186    "\nError %d: Non-optional IUP (like LOCL, WCOD) inside IUPs list (in FTPR manifest extension) is not in the Update Image.\n"
#define ID_ERROR_187    "\nError %d: PMC partition is not in the Update Image.\n"
#define ID_ERROR_188    "\nError %d: It is not allowed to do Partial Update on this partition.\n"
#define ID_ERROR_189    "\nError %d: It is not allowed to do Partial Update on Type-C partitions, according to NVAR.\n"
#define ID_ERROR_190    "\nError %d: RBEP and NFTP must have the same version as FTPR, in the Update Image.\n"
#define ID_ERROR_191    "\nError %d: RBEP and NFTP must have the same SVN as FTPR, in the Update Image.\n"
#define ID_ERROR_192    "\nError %d: RBEP and NFTP must have the same VCN as FTPR, in the Update Image.\n"
#define ID_ERROR_193    "\nError %d: Non-optional IUPs (like LOCL, WCOD) must have the same major build version as FTPR, in the Update Image for Full Update, in the Flash Image for Partial Update.\n"
#define ID_ERROR_194    "\nError %d: Update IUP must not have SVN smaller than SVN of Flash IUP.\n"
#define ID_ERROR_195    "\nError %d: Update IUP must not have VCN smaller than VCN of Flash IUP.\n"
#define ID_ERROR_196    "\nError %d: Update Image length is not the same as Flash Image length.\n"
#define ID_ERROR_197    "\nError %d: Update from PV bit ON to PV bit OFF is not allowed.\n"
#define ID_ERROR_198    "\nError %d: Update to PV bit OFF on Revenue platform is not allowed.\n"
#define ID_ERROR_199    "\nError %d: Update to higher SVN must be an upgrade - to higher build version.\n"
#define ID_ERROR_200    "\nError %d: Update to higher SVN must be to a higher Hot Fix number (the third number in the build version).\n"
#define ID_ERROR_201    "\nError %d: Place holder. This error code will not be returned by the FW.\n"
#define ID_ERROR_202    "\nError %d: Place holder. This error code will not be returned by the FW.\n"
#define ID_ERROR_203    "\nError %d: Place holder. This error code will not be returned by the FW.\n"
#define ID_ERROR_204    "\nError %d: Place holder. This error code will not be returned by the FW.\n"
#define ID_ERROR_205    "\nError %d: PMCP must have the same major API version as the version inside the list in FTPR, in the Update Image for Full Update.\n"
#define ID_ERROR_206    "\nError %d: OEMP must have the same major API version as the version inside the list in FTPR, in the Update Image for Full Update.\n"
#define ID_ERROR_207    "\nError %d: WCOD must have the same major API version as the version inside the list in FTPR, in the Update Image for Full Update, in the Flash Image for Partial Update.\n"
#define ID_ERROR_208    "\nError %d: LOCL must have the same major API version as the version inside the list in FTPR, in the Update Image for Full Update, in the Flash Image for Partial Update.\n"
#define ID_ERROR_209    "\nError %d: PAVP must have the same major API version as the version inside the list in FTPR, in the Update Image for Full Update, in the Flash Image for Partial Update.\n"
#define ID_ERROR_210    "\nError %d: IOMP must have the same major API version as the version inside the list in FTPR, in the Update Image for Full Update, in the Flash Image for Partial Update.\n"
#define ID_ERROR_211    "\nError %d: MGPP must have the same major API version as the version inside the list in FTPR, in the Update Image for Full Update, in the Flash Image for Partial Update.\n"
#define ID_ERROR_212    "\nError %d: TBTP must have the same major API version as the version inside the list in FTPR, in the Update Image for Full Update, in the Flash Image for Partial Update.\n"
#define ID_ERROR_213    "\nError %d: ISHC must have the same major API version as the version inside the list in FTPR, in the Update Image for Full Update, in the Flash Image for Partial Update.\n"
#define ID_ERROR_214    "\nError %d: IUNP must have the same major API version as the version inside the list in FTPR, in the Update Image for Full Update, in the Flash Image for Partial Update.\n"
#define ID_ERROR_215    "\nError %d: Place holder. This error code will not be returned by the FW.\n"
#define ID_ERROR_216    "\nError %d: Non-optional IUP (like LOCL, WCOD) inside IUPs list (in FTPR manifest extension) is not in the Flash Image.\n"
#define ID_ERROR_217    "\nError %d: A partition that was searched in the Update Image is not in it.\n"
#define ID_ERROR_218    "\nError %d: Update between engineering build vs regular build is not allowed. Both builds have to be the same type: regular or engineering build. Engineering build is 7000 and above. Regular build is below 7000.\n"
#define ID_ERROR_219    "\nError %d: OEM KM partition is not in the Update Image, but ISHC/IUNP is in the Update Image, which is not allowed.\n"
#define ID_ERROR_220    "\nError %d: ISHC/IUNP do not exist in the same way in the Update Image and in the Flash Image.\n"
#define ID_ERROR_221    "\nError %d: OEM KM partition is not in the Flash Image, but it is in the Update Image, which is not allowed.\n"
#define ID_ERROR_222    "\nError %d: Partial FW Update: the Update Image contains IUP that is different than the one that was requested to be updated in the Partial Update command.\n"
#define ID_ERROR_223    "\nError %d: The Partial Update Image size is different than the size of the IUP in it (as it is in the manifest). This means that the Update Image contains more (or less) than the IUP partition.\n"
#define ID_ERROR_224    "\nError %d: Bug: Open of IUP path failed. Need to add the path in Storage, or add permissions to FW Update process.\n"
#define ID_ERROR_225    "\nError %d: Bug: spi_flash_partition_updated() failed. This updates the files (in the file system) of the newly updated IUP, after Partial Update (without reset).\n"
#define ID_ERROR_226    "\nError %d: Update Rule file contains invalid value. (This file holds the MEBX option for FW Update: values: disable / enable / password protected).\n"
#define ID_ERROR_227    "\nError %d: Call to pwdmgr function failed. pwdmgr_get_mebx_pwd() - to get the ME password, for FW Update that requires password.\n"
#define ID_ERROR_228    "\nError %d: Call to pwr function failed. pwr_state_get_last_reset_reason().\n"
#define ID_ERROR_229    "\nError %d: Call to spi function failed. spi_flash_get_override_strap().\n"
#define ID_ERROR_230    "\nError %d: Get Restore Point Image is not allowed, because a previous Get Restore Point operation already started. Both operations will be aborted. (Get Restore Point can be started again after this).\n"
#define ID_ERROR_231    "\nError %d: Bug: Get Restore Point Image Data: The offset of Restore Point Image is bigger than the Image length.\n"
#define ID_ERROR_232    "\nError %d: Heci message length is not as expected.\n"
#define ID_ERROR_233    "\nError %d: FWU_START_MSG Heci message contains invalid value in UpdateEnvironment. Value should be FWU_ENV_MANUFACTURING. (Other possible value: FWU_ENV_IFU is obsolete).\n"
#define ID_ERROR_234    "\nError %d: FWU_DATA Heci command was sent, but the FW Update wasn't started with FWU_START Heci command before it.\n"
#define ID_ERROR_235    "\nError %d: FWU_DATA Heci command has invalid data length (too big).\n"
#define ID_ERROR_236    "\nError %d: FWU_END Heci command was sent, but there was no FWU_DATA command before it.\n"
#define ID_ERROR_237    "\nError %d: Error when flushing NVM to UMA space (before rewriting flash).\n"
#define ID_ERROR_238    "\nError %d: clear_ipk_valid_bit() returned error. This function prevents CSE from entering M3 after FW Update, and instead CSE will go into MOff.\n"
#define ID_ERROR_239    "\nError %d: FW Update process called to PG entry override (sys_pg_override()) at the start of the update, and it returned error.\n"
#define ID_ERROR_240    "\nError %d: Flash Image content is invalid (partitions/manifests sizes, locations, structures). \n"
#define ID_ERROR_241    "\nError %d: Wrong structure of Update Image (manifests, $CPD), complete_partition_length is 0, no module or metadata of preupdate inside UPDT partition. \n"
#define ID_ERROR_242    "\nError %d: Base image was provided, but base image doesn't contain independent updatable partitions (IUPs).\n"
#define ID_ERROR_243    "\nError %d: Provided image is missing IUNP partition.\n"
#define ID_ERROR_244    "\nError %d: Provided image is missing ISHC partition.\n"
#define ID_ERROR_245    "\nError %d: Provided image contains IUNP partition but the existing image on the platform doesn't contain it.\n"
#define ID_ERROR_246    "\nError %d: Provided image contains ISHC partition but the existing image on the platform doesn't contain it.\n"
#define ID_ERROR_247    "\nError %d: Provided image contains ISHC or/and IUNP partitions but not the OEM Key manifest partition.\n"
#define ID_ERROR_248    "\nError %d: Provided image contains OEM Key manifest partition but the current platform image don't contain such partition.\n"
#define ID_ERROR_249    "\nError %d: Display Partition Vendor ID failed.\n"
#define ID_ERROR_250    "\nError %d: Invalid Partition ID. Use a Partition ID which is on the Flash Image.\n"
#define ID_ERROR_251    "\nError %d: Update to higher TCB SVN must be also to higher ARB SVN.\n"
#define ID_ERROR_252    "\nError %d: Loader failed to verify manifest signature of DPHY.\n"
#define ID_ERROR_253    "\nError %d: Some manifest extension is missing in DPHY. Wrong MEU Tool was used to create the partition.\n"
#define ID_ERROR_254    "\nError %d: DPHY partition hash and calculated hash are not the same. If partition hash is zero - wrong MEU Tool was used to create the partition.\n"
#define ID_ERROR_255    "\nError %d: DPHY must have the same major API version as the version inside the list in FTPR, in the Update Image for Full Update, in the Flash Image for Partial Update.\n"


//
// Specify the OEM ID to be passed to the ME
// The bit order must match what was created with FITC.
//
// For example:
// FITC Setting: 00000000-0001-0000-0000-00000000001
// MEINFO.EXE returns: 00000000-0001-0000-0000-00000000001
// 
// mOemId would be: 
//  _UUID                      mOemId = {0x00000000, 0x0001, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
//
_UUID                      mOemId = {0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};


//Defines
// Last Reset Types
/*#define NORESET 0
#define HOSTRESET  1
#define MERESET  2
#define GLOBALRESET 3*/

#define MFT_PART_INFO_EXT_UPDATE_ACTION_NONE         0
#define MFT_PART_INFO_EXT_UPDATE_ACTION_HOST_RESET   1
#define MFT_PART_INFO_EXT_UPDATE_ACTION_CSE_RESET    2
#define MFT_PART_INFO_EXT_UPDATE_ACTION_GLOBAL_RESET 3

// Get Interface
#define FW_UPDATE_DISABLED 0
#define FW_UPDATE_ENABLED 1
#define FW_UPDATE_PASSWORD_PROTECTED 2

//
//
//  MSFT compiler uses this variable to inform itself whether floating
//  point support is loaded.
//
/*
int _fltused;

unsigned int      index = 0;
signed int        timer30s = 0;

FlashVersion  mVersion;
*/
/*
//
// Print a message to the desired output device
// Customize for platform
//
void DisplayConsoleMessage (
IN CHAR16 *String
)
{
Print(String);
}
*/

int PerformUpdate(char* ImageBuffer);

/*
int CheckFileExt(char *file)
{
    size_t len = 0;
    char* begin = NULL;
    char* end = NULL;

    if (NULL == file)
    {
        return 1;
    }

    len = strlen(file);
	if (len == 0)
    {
        return 1;
    }
    end = file + len - 1;

    while(*end != '.' && end != file)
    {
        end--;
    }

    begin = end+1;

    printf("File Extension: %s\n",begin);


    if (!_stricmp(begin,"bin"))
    {
        return 1;
    }

    return 0;
}
*/

void DisplaySendStatus(float BytesSent, float BytestobeSent)
{
   UINT32 Value = (UINT32)(BytesSent * 100 / BytestobeSent);

    if (Value != 100)
    {
        printf ("Sending the update image to FW for verification:  [ %d%% ]\r", Value);
    }
    else
    {
        printf ("Sending the update image to FW for verification:  [ COMPLETE ] \n");
    }
}


void DisplayTextForReturnErrorCode(UINT32 Code)
{
    switch(Code) {
    case FWU_NO_MEMORY:
        printf (ID_ERROR_3, FWU_NO_MEMORY);
        break;
    case FWU_UPDATE_TIMEOUT:
        printf (ID_ERROR_4, FWU_UPDATE_TIMEOUT);
        break;
    case FWU_IMG_HEADER:
        printf (ID_ERROR_7, FWU_IMG_HEADER);
        break;
    case FWU_SGN_MISMATCH:
        printf (ID_ERROR_8, FWU_SGN_MISMATCH);
        break;
    case FWU_SKU_MISMATCH: 
        printf (ID_ERROR_9, FWU_SKU_MISMATCH);
        break;
    case FWU_VER_MISMATCH:
        printf (ID_ERROR_10, FWU_VER_MISMATCH);
        break;
    case FWU_USAGE_ERROR:
        printf (ID_ERROR_18, FWU_USAGE_ERROR);
        break;
    case FWU_USAGE_ERROR_B:
        printf (ID_ERROR_18B, FWU_USAGE_ERROR_B);
        break;
    case FWU_LAST_STATUS:
        printf (ID_ERROR_19, FWU_LAST_STATUS);
        break;
    case FWU_GET_VER_ERR:
        printf (ID_ERROR_24 , FWU_GET_VER_ERR);
        break;
    case FWU_AUDIT_POLICY_FAILURE:
        printf (ID_ERROR_25C, FWU_GENERAL);
        break;
    case FWU_ERROR_CREATING_FT:
        printf (ID_ERROR_25C, FWU_GENERAL);
        break;
    case FWU_SAL_NOTIFICATION_ERROR:
        printf (ID_ERROR_25A, FWU_GENERAL);
        break;
    case FWU_NO_UPDATE:
        printf (ID_ERROR_27, FWU_NO_UPDATE);
        break;
    case FWU_LOCAL_DIS:
        printf (ID_ERROR_29, FWU_LOCAL_DIS);
        break;
    case FWU_VERIFY_OEM_ID_ERR:
        printf (ID_ERROR_22 , FWU_VERIFY_OEM_ID_ERR);
        break;
    case FWU_INVALID_OEM_ID:
        printf (ID_ERROR_33, FWU_INVALID_OEM_ID);
        break;
    case FWU_FILE_OPEN:
        printf (ID_ERROR_34, FWU_FILE_OPEN);
        break;
    case FWU_IME_SMALL_BUFF:
        printf (ID_ERROR_36, FWU_IME_SMALL_BUFF);
        break;
    case FWU_IME_NO_DEVICE:
        printf (ID_ERROR_37, FWU_IME_NO_DEVICE);
        break;
    case FWU_IME_NOT_READY:
        printf (ID_ERROR_38, FWU_IME_NOT_READY);
        break;
    case FWU_IME_UN_SUP_MESS:
        printf (ID_ERROR_39, FWU_IME_UN_SUP_MESS);
        break;
    case FWU_INVALID_IMG_LENGTH:
        printf (ID_ERROR_40, FWU_INVALID_IMG_LENGTH);
        break;
    case FWU_GLBL_BUFF_UNAVAILABLE:
        printf (ID_ERROR_41, FWU_GLBL_BUFF_UNAVAILABLE);
        break;
    case FWU_INVALID_FW_PARAMS:
        printf (ID_ERROR_44, FWU_INVALID_FW_PARAMS);
        break;
    case FWU_FILE_WRITE:
        printf (ID_ERROR_55, FWU_FILE_WRITE);
        break;
    case FWU_DISPLAY_FW_VERSION:
        printf (ID_ERROR_56, FWU_DISPLAY_FW_VERSION);
        break;
    case FWU_IMAGE_UNDER_VCN:
        printf(ID_ERROR_57, FWU_IMAGE_UNDER_VCN);
        break;
    case FWU_IMAGE_VER_HIST_CHK_FAIL:
        printf (ID_ERROR_58, FWU_IMAGE_VER_HIST_CHK_FAIL);
        break;
    case FWU_DOWNGRADE_VETOED:
        printf (ID_ERROR_59, FWU_DOWNGRADE_VETOED);
        break;
    case FWU_FW_WRITE_FILE_FAIL:
        printf (ID_ERROR_60, FWU_FW_WRITE_FILE_FAIL);
        break;
    case FWU_FW_READ_FILE_FAIL:
        printf (ID_ERROR_61, FWU_FW_READ_FILE_FAIL);
        break;
    case FWU_FW_DELETE_FILE_FAIL:
        printf (ID_ERROR_62, FWU_FW_DELETE_FILE_FAIL);
        break;
    case FWU_PARTITION_LAYOUT_NOT_COMP:
        printf (ID_ERROR_63, FWU_PARTITION_LAYOUT_NOT_COMP);
        break;
    case FWU_DOWNGRADE_NOT_ALLOWED_DATA_MISMATCH:
        printf ("\nDowngrade is NOT permitted due to mismatched data format version.\n");
        printf (ID_ERROR_64, FWU_DOWNGRADE_NOT_ALLOWED_DATA_MISMATCH);
        break;
    case FWU_UPDATE_PASSWORD_NOT_MATCHED:
        printf (ID_ERROR_65, FWU_UPDATE_PASSWORD_NOT_MATCHED);
        break;
    case FWU_UPDATE_PASSWORD_EXCEED_MAXIMUM_RETRY:
        printf (ID_ERROR_66, FWU_UPDATE_PASSWORD_EXCEED_MAXIMUM_RETRY);
        printf (ID_INFO_16);
        break;
    case FWU_PID_NOT_EXPECTED:
        printf (ID_ERROR_72, FWU_PID_NOT_EXPECTED);
        break;
    case FWU_FILE_ALREADY_EXISTS:
        printf ("Error %d: File already exists\n", FWU_FILE_ALREADY_EXISTS);
        break;
    case FWU_FILE_INVALID:
        printf ("Error %d: Invalid File\n", FWU_FILE_INVALID);
        break;
    case FWU_SAVE_RESTORE_POINT_ERROR:
        printf ("\nError %d: Restore Point Image Failure\n", FWU_SAVE_RESTORE_POINT_ERROR);
        break;
    case FWU_GET_BLIST_ERROR:
        printf ("\nError %d: Get Black List Failure\n" , FWU_GET_BLIST_ERROR);
        break;
    case FWU_GET_PATTRIB_ERROR:
        printf ("\nError %d: Get Partition Attribute Failure\n" , FWU_GET_PATTRIB_ERROR);
        break;
    case FWU_GET_UPD_INFO_STATUS:
        printf ("\nError %d: Get Update Info Status Failure\n" , FWU_GET_UPD_INFO_STATUS);
        break;
    case FWU_BUFFER_COPY_FAILED:
        printf ("\nError %d:Buffer Copy Failure\n" , FWU_BUFFER_COPY_FAILED);
        break;
    case FWU_ERROR_PMC_INSTANCE:
        printf(ID_ERROR_116, FWU_ERROR_PMC_INSTANCE);
        break;
    case FWU_ERROR_H_LP_MISMATCH:
        printf(ID_ERROR_117, FWU_ERROR_H_LP_MISMATCH);
        break;
    default:
        printf (ID_ERROR_25, FWU_GENERAL);
        break;
    }
}



//sample code
void usage(void)
{
    printf(" -f <name>  Input file to perform Fwupdate.\n");
    printf(" -h     Display Usage options.\n");
    printf(" Note: Please run the Application with administrative privileges.\n");
    exit (0);
}

int main(int argc, char *argv[])
{
    //char* ImageFile;

    printf("Program name: %s\n\n", argv[0]);

    if ((argc > 1) && (argv[1][0] == '-'))
    {
        switch (argv[1][1])
        {
        case 'f':
            printf("%s\n",&argv[1][2]);
            printf("Usage option: %s\n", &argv[1][1]);
            printf("sub param: %s\n", &argv[2][0]);
            PerformUpdate(&argv[2][0]);
            break;
        case 'h':
            usage();
            break;
        default:
            printf("Invalid Argument: %s\n", argv[1]);
            usage();
        }
    }
    return (0);

}

// This fucntion prints the progress bar line during hte fw update process. 
static UINT32 ProgressDot(int timer30s)
{
    // new code
    INT32 i = 0;
    char string[3][80] = {
        "                       Do not Interrupt", 
        "                       Do not Interrupt", 
        "                       Do not Interrupt"};

    for (i = 0; i < 3; i++)
    {
        printf ("Progress Dot %s \r", string[i]);

        Sleep(250);
        timer30s += 250;
    }
    return 0;
} 

// end sample code

int PerformUpdate(char* ImageBuffer)
{
    UINT32            Status;
    UINT32            ImageLength = 0;
    BOOLEAN           bAllowSV = TRUE;
//    BOOLEAN           bUsePassword;
//    BOOLEAN           bPid;
//    BOOLEAN           bF;
    char              *Password = NULL;
    //CHAR              Password[9];
    UINT32            FWUpdateStatus;
//    DWORD             loops = 500;
    //BOOLEAN           done = FALSE;
    UINT32            lastStatus = 0;
    //UINT32            platCheck = 0;
//    FWVersion         fwVersion;
    //INT32             platCheckReturn = 0; 
    UINT32            CheckPolicyStatus = 0;
    UPDATE_TYPE       Upd_Type;
    VersionLib        ver;
    UINT32            index = 0;
//    UINT32            status;
    UINT32            UpdateStatus = 0;
    UINT32            TotalStages = 0;
    UINT32            PercentWritten = 0;  
    char              symbol = 0;
    UINT32            lastResetType;
    UPDATE_FLAGS_LIB  update_flags;
    UINT16            interfaces;
    int               timer30s = 0;
    unsigned int       indexMod;
    int                percentage0s = 0;
    int                percentdiff = 0;
    //UINT32             ComparePartID = 0;
    //UINT32             hexValueInstId = 0;
//    IPU_UPDATED_INFO   IpuUpdatedInfo;
    //UINT32             PartId = 0;
    UINT32             g_fwuError;
//    FWU_GET_IPU_PT_ATTRB_MSG_REPLY FwuGetIpuAttrbMsgInfo;
    //BOOLEAN            found = FALSE;
//    UINT32             i, j = 0;
    UINT16 major = 0;
    UINT16 minor = 0;
    UINT16 hotfix = 0;
    UINT16 build = 0;
    UINT32 itr = 0;
//    UINT32               RuleData;
    UINT32 Fwtype = 0;
    UINT32 sku =0;
    char OEMID[37] = {0};
    UINT32 continueLoop;

    //Zero out the update flag structure
    memset(&update_flags,0,sizeof(UPDATE_FLAGS_LIB));

    printf ("\nIntel (R) Firmware Update Utility Sample Application \n");

    GetFwType(&Fwtype);
    if (Fwtype) 
        printf("\n FW Type: Corporate \n");
    else 
        printf("\n FW Type: Consumer \n");

    GetOemID(OEMID, 37);
    //cout << OEMID;
    printf("\n OEM ID : %s \n", OEMID);
    
    GetPchSKU(&sku);
    //TextOutput(MESSAGE_NORMAL, "\n possible options: H == 0, LP == 1. FwType is %d\n", FwType)
    if (sku) 
        printf("\n PCH Sku : LP \n"); 
    else 
        printf("\n PCH Sku : H \n");
    printf("\n");

    if (ImageBuffer == NULL)
    {
        if((g_fwuError = GetFwVersion((const TCHAR *)ImageBuffer,&major,&minor,&hotfix,&build)))
        {
            DisplayTextForReturnErrorCode(g_fwuError);
            printf("\nSTATUS: display FW version failed.\n");
        }
        else
        {
            printf("FW Version: %i.%i.%i.%i\n",major,minor,hotfix,build);
            g_fwuError = FWU_ERROR_SUCCESS;
        }
		
		return FWU_ERROR_SUCCESS;
    }
    
    // end of sample code to check the file type

    //
    // Get the current status of the ME FWUpdate Client - verifies if the client is 
    // installed
    //
    if (GetLastStatus(&lastStatus)) {
        printf (ID_ERROR_19, FWU_LAST_STATUS);
        return FWU_ERROR_SUCCESS;
    }

    //
    // Is there a pending reset?
    //
    if (GetLastUpdateResetType (&lastResetType)) { 
        printf (ID_ERROR_19, FWU_LAST_STATUS);
        return FWU_ERROR_SUCCESS;
    }

    if (STATUS_UPDATE_HOST_RESET_REQUIRED == lastStatus) {
        printf (ID_ERROR_51, FWU_REBOOT_NEEDED);
        return FWU_ERROR_SUCCESS;
    }

    switch (lastResetType) {
    case MFT_PART_INFO_EXT_UPDATE_ACTION_HOST_RESET:

    case MFT_PART_INFO_EXT_UPDATE_ACTION_GLOBAL_RESET:
        printf (ID_ERROR_51, FWU_REBOOT_NEEDED);
        return FWU_ERROR_SUCCESS;
        //break;
    default:
        break;
    }

    printf (ID_INFO_3);

    //
    // Is update supported? 
    //
    if (GetInterfaces (&interfaces)) {
        printf (ID_ERROR_19, FWU_LAST_STATUS);
        return FWU_ERROR_SUCCESS;
    }

    switch (interfaces) {
    case FW_UPDATE_DISABLED:
        printf ("Local FWUpdate is Disabled\n"); 
        return FWU_ERROR_SUCCESS;
    case FW_UPDATE_PASSWORD_PROTECTED:
        printf ("Local FWUpdate is Password Protected\n"); 
        break;
    case FW_UPDATE_ENABLED:
        break;
    default:
        break;
    }


    printf ("Checking firmware parameters...\n");

    CheckPolicyStatus = CheckPolicyBuffer((unsigned char*)ImageBuffer, (INT32)ImageLength, (INT32)bAllowSV, &Upd_Type, &ver);          

    switch (Upd_Type) {
    case DOWNGRADE_SUCCESS:
    case SAMEVERSION_SUCCESS:
    case UPGRADE_SUCCESS:
        break;

    case DOWNGRADE_FAILURE:
        printf ("FW Update downgrade not allowed\n");
        return FWU_ERROR_SUCCESS;
        //break;
    case SAMEVERSION_FAILURE:
        printf ("FW Update same version not allowed, specify /s on command line\n");
        return FWU_ERROR_SUCCESS;

    default:
        break;
    }

    //
    // Password hack for testing - replace with OEM version if password required
    // 
    /*if (!bUsePassword) {
        memset (Password,0, sizeof (Password));
    }*/

    FWUpdateStatus = FwUpdateFull(ImageBuffer,Password,0,FWU_ENV_MANUFACTURING,mOemId, update_flags,&DisplaySendStatus);

    if (FWU_ERROR_SUCCESS != FWUpdateStatus) {
        DisplayTextForReturnErrorCode(FWUpdateStatus);
        return FWU_ERROR_SUCCESS;
    }

    // 
    // Image downloaded to FW Update Client
    // Now query the status of the update being applied
    //

    printf ("\nFW Update:  [  0 %% ]\r");
    index = 0;

    // 
    // Loop through Polling for Fw Update Stages
    //
    ProgressDot(timer30s);
    do {
        //We mod4 the index to determine which ascii animation frame to display for this iteration.
        indexMod = (++index % 4);
        //symbol = (++index % 2 == 0)?'|': '-';
        switch(indexMod)
            //loop through (|) (/) (-) (\) (|) (/) ...
        {
        case CMD_LINE_STATUS_UPDATE_1: symbol =  '|';  break;
        case CMD_LINE_STATUS_UPDATE_2: symbol =  '/';  break;
        case CMD_LINE_STATUS_UPDATE_3: symbol =  '-';  break;
        case CMD_LINE_STATUS_UPDATE_4: symbol =  '\\'; break;
        }

        //Loop to retry 3 times when there is a Heci Send or Receive failure
        itr = 0;
        do
        {
            //Loop to retry 3 times when there is a Heci Send or Receive failure
            Status = FWUpdate_QueryStatus_Get_Response(&UpdateStatus, &TotalStages,
                &PercentWritten, &lastStatus, &lastResetType);

            // *** TODO check status before checking PercentWritten 
            //don't print Fw Update percent if its more than 100% (its probably error value)
            if (PercentWritten > 100)
            {
                break;
            }

            printf("FW Update:  [ %d%% (%c)]\r" ,PercentWritten, symbol);

            itr++;
        } while (Status == FWU_IME_NOT_READY && itr < 3);

        Sleep(250);
        if (timer30s >= 30000) 
        {
            percentdiff = PercentWritten - percentage0s;
            if (percentdiff == 0)
            {
                Status = FWU_UPDATE_TIMEOUT;
                break;
            }

            percentage0s = PercentWritten;
            timer30s = 0;
        }
        else 
        {
            timer30s+=250;
        }

        if (UpdateStatus != HECI1_CSE_GS1_PHASE_FWUPDATE)// we are NOT in FW update phase
        {
            if (lastStatus == STATUS_UPDATE_NOT_READY)// waiting for HECI message -> continue to wait
                continueLoop = 1;
            else 
                continueLoop = 0;
        }
        else //we are in FW update phase
        {
            if (PercentWritten == 100) //FWupdate proccess completed successfully -> exit
                continueLoop = 0;
            else 
            {
                if (lastStatus == STATUS_UPDATE_SUCCESS) //FWupdate proccess in progress (0-99%) -> continue loop
                    continueLoop = 1;
                else // we got error from FW update (progress) registers e.g. 127 (0x7F) and not a value between 0-99%
                {
                    if (lastStatus == STATUS_UPDATE_NOT_READY) // waiting for HECI message -> continue to wait
                        continueLoop = 1;
                    else
                        continueLoop = 0;
                }
            }
        }
    } while (continueLoop);

    switch (Status) {
    case FWU_NO_MEMORY:
    case FWU_IME_NO_DEVICE:
        printf (ID_ERROR_68, FWU_UPDATE_POLLING_FAILED);
        return Status;
    case FWU_IME_NOT_READY:
    case FWU_UPDATE_TIMEOUT:
        DisplayTextForReturnErrorCode(Status);
        return Status;
    case FWU_ERROR_FW:
        printf (ID_ERROR_69, FWU_ERROR_FW);
        return Status;
    default:
        break;
    }

    switch (lastStatus) {
    case STATUS_UPDATE_SUCCESS:
        if(PercentWritten == 99)
        {
            printf("\nFW Update:  [  100 %% ]\r");
        }

        switch (lastResetType) {

        case MFT_PART_INFO_EXT_UPDATE_ACTION_NONE:

        case MFT_PART_INFO_EXT_UPDATE_ACTION_CSE_RESET:
            printf ("\nFW Update is completed successfully.\n");
            break;
        case MFT_PART_INFO_EXT_UPDATE_ACTION_HOST_RESET:

        case MFT_PART_INFO_EXT_UPDATE_ACTION_GLOBAL_RESET:
            printf ("\nFW Update is complete and a reboot will run the new FW.\n");
            break;
        default:
            printf ("\nFW Update is complete and a reboot will run the new FW.\n");
            break;
        }
        break;
    case STATUS_UPDATE_INVALID_UPDATE_IMAGE:
        DisplayTextForReturnErrorCode(FWU_IMG_HEADER);
        break;
    case STATUS_UPDATE_INTEGRITY_FAILURE:
        DisplayTextForReturnErrorCode(FWU_SGN_MISMATCH);
        break;
    case STATUS_UPDATE_SKU_MISMATCH:
        DisplayTextForReturnErrorCode(FWU_SKU_MISMATCH);
        break;
    case STATUS_UPDATE_FW_VERSION_MISMATCH:
        DisplayTextForReturnErrorCode(FWU_VER_MISMATCH);
        break;
    case STATUS_UPDATE_GENERAL_FAILURE:
        DisplayTextForReturnErrorCode(FWU_GENERAL);
        break;
    case STATUS_UPDATE_OUT_OF_RESOURCES:
        DisplayTextForReturnErrorCode(FWU_NO_MEMORY);
        break;
    case STATUS_UPDATE_AUDIT_POLICY_FAILURE:
        DisplayTextForReturnErrorCode(FWU_AUDIT_POLICY_FAILURE);
        break;
    case STATUS_UPDATE_ERROR_CREATING_FT:
        DisplayTextForReturnErrorCode(FWU_ERROR_CREATING_FT);
        break;
    case STATUS_UPDATE_SAL_NOTIFICATION_ERROR:
        DisplayTextForReturnErrorCode(FWU_SAL_NOTIFICATION_ERROR);
        break;
    case STATUS_INVALID_OEM_ID:
        DisplayTextForReturnErrorCode(FWU_INVALID_OEM_ID);
        break;
    case STATUS_DOWNGRADE_NOT_ALLOWED_VCN_RESTRICTION:
        DisplayTextForReturnErrorCode(FWU_IMAGE_UNDER_VCN);
        break; 
    case STATUS_DOWNGRADE_NOT_ALLOWED_SVN_RESTRICTION:
        printf("\nFW downgrade is not allowed due to SVN restriction.\n");
        break;
    case STATUS_UPDATE_IMAGE_BLACKLISTED:
        printf("\nFW Update/downgrade is not allowed to the supplied FW image.\n");
        break;
    default:
        printf("\nlastStatus = %d\n",lastStatus);
        DisplayTextForReturnErrorCode(FWU_GENERAL);
        break;
    }

    return FWU_ERROR_SUCCESS;
}

