15a582d3cSFaisal Awada /**
25a582d3cSFaisal Awada * Copyright © 2024 IBM Corporation
35a582d3cSFaisal Awada *
45a582d3cSFaisal Awada * Licensed under the Apache License, Version 2.0 (the "License");
55a582d3cSFaisal Awada * you may not use this file except in compliance with the License.
65a582d3cSFaisal Awada * You may obtain a copy of the License at
75a582d3cSFaisal Awada *
85a582d3cSFaisal Awada * http://www.apache.org/licenses/LICENSE-2.0
95a582d3cSFaisal Awada *
105a582d3cSFaisal Awada * Unless required by applicable law or agreed to in writing, software
115a582d3cSFaisal Awada * distributed under the License is distributed on an "AS IS" BASIS,
125a582d3cSFaisal Awada * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135a582d3cSFaisal Awada * See the License for the specific language governing permissions and
145a582d3cSFaisal Awada * limitations under the License.
155a582d3cSFaisal Awada */
165a582d3cSFaisal Awada
175a582d3cSFaisal Awada #include "config.h"
185a582d3cSFaisal Awada
195a582d3cSFaisal Awada #include "aei_updater.hpp"
205a582d3cSFaisal Awada
215a582d3cSFaisal Awada #include "pmbus.hpp"
225a582d3cSFaisal Awada #include "types.hpp"
235a582d3cSFaisal Awada #include "updater.hpp"
245a582d3cSFaisal Awada #include "utility.hpp"
25*57fb664cSFaisal Awada #include "utils.hpp"
265a582d3cSFaisal Awada
275a582d3cSFaisal Awada #include <phosphor-logging/lg2.hpp>
285a582d3cSFaisal Awada
298dca5075SFaisal Awada #include <fstream>
30*57fb664cSFaisal Awada #include <system_error>
318dca5075SFaisal Awada
325a582d3cSFaisal Awada namespace aeiUpdater
335a582d3cSFaisal Awada {
34f0c0c47bSJayanth Othayoth
355a582d3cSFaisal Awada constexpr uint8_t MAX_RETRIES = 0x02; // Constants for retry limits
365a582d3cSFaisal Awada
375a582d3cSFaisal Awada constexpr int ISP_STATUS_DELAY = 1200; // Delay for ISP status check (1.2s)
385a582d3cSFaisal Awada constexpr int MEM_WRITE_DELAY = 5000; // Memory write delay (5s)
395ace9fb7SFaisal Awada constexpr int MEM_STRETCH_DELAY = 1; // Delay between writes (1ms)
405a582d3cSFaisal Awada constexpr int MEM_COMPLETE_DELAY = 2000; // Delay before completion (2s)
415a582d3cSFaisal Awada constexpr int REBOOT_DELAY = 8000; // Delay for reboot (8s)
425a582d3cSFaisal Awada
435a582d3cSFaisal Awada constexpr uint8_t I2C_SMBUS_BLOCK_MAX = 0x20; // Max Read bytes from PSU
445a582d3cSFaisal Awada constexpr uint8_t FW_READ_BLOCK_SIZE = 0x20; // Read bytes from FW file
455a582d3cSFaisal Awada constexpr uint8_t BLOCK_WRITE_SIZE = 0x25; // I2C block write size
465ace9fb7SFaisal Awada
475a582d3cSFaisal Awada constexpr uint8_t START_SEQUENCE_INDEX = 0x1; // Starting sequence index
485ace9fb7SFaisal Awada constexpr uint8_t STATUS_CML_INDEX = 0x4; // Status CML read index
495ace9fb7SFaisal Awada constexpr uint8_t EXPECTED_MEM_READ_REPLY = 0x5; // Expected memory read reply
505ace9fb7SFaisal Awada // size after write data
515a582d3cSFaisal Awada
525a582d3cSFaisal Awada // Register addresses for commands.
535a582d3cSFaisal Awada constexpr uint8_t KEY_REGISTER = 0xF6; // Key register
545a582d3cSFaisal Awada constexpr uint8_t STATUS_REGISTER = 0xF7; // Status register
555a582d3cSFaisal Awada constexpr uint8_t ISP_MEMORY_REGISTER = 0xF9; // ISP memory register
565a582d3cSFaisal Awada
575a582d3cSFaisal Awada // Define AEI ISP status register commands
585a582d3cSFaisal Awada constexpr uint8_t CMD_CLEAR_STATUS = 0x0; // Clear the status register
595a582d3cSFaisal Awada constexpr uint8_t CMD_RESET_SEQ = 0x01; // This command will reset ISP OS for
605a582d3cSFaisal Awada // another attempt of a sequential
615a582d3cSFaisal Awada // programming operation.
625a582d3cSFaisal Awada constexpr uint8_t CMD_BOOT_ISP = 0x02; // Boot the In-System Programming System.
635a582d3cSFaisal Awada constexpr uint8_t CMD_BOOT_PWR = 0x03; // Attempt to boot the Power Management
645a582d3cSFaisal Awada // OS.
655a582d3cSFaisal Awada
665a582d3cSFaisal Awada // Define AEI ISP response status bit
675a582d3cSFaisal Awada constexpr uint8_t B_ISP_MODE = 0x40; // ISP mode
685a582d3cSFaisal Awada constexpr uint8_t B_ISP_MODE_CHKSUM_GOOD = 0x41; // ISP mode & good checksum.
698dca5075SFaisal Awada constexpr uint8_t SUCCESSFUL_ISP_REBOOT_STATUS = 0x0; // Successful ISP reboot
708dca5075SFaisal Awada // status
715a582d3cSFaisal Awada using namespace phosphor::logging;
725a582d3cSFaisal Awada namespace util = phosphor::power::util;
735a582d3cSFaisal Awada
doUpdate()745a582d3cSFaisal Awada int AeiUpdater::doUpdate()
755a582d3cSFaisal Awada {
765a582d3cSFaisal Awada i2cInterface = Updater::getI2C();
77*57fb664cSFaisal Awada enableEventLogging();
785a582d3cSFaisal Awada if (i2cInterface == nullptr)
795a582d3cSFaisal Awada {
80*57fb664cSFaisal Awada // Report serviceable error
81*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
82*57fb664cSFaisal Awada {"I2C_INTERFACE", "I2C interface is null pointer."}};
83*57fb664cSFaisal Awada // Callout PSU & I2C
84*57fb664cSFaisal Awada callOutI2CEventLog(additionalData);
85*57fb664cSFaisal Awada
865a582d3cSFaisal Awada throw std::runtime_error("I2C interface error");
875a582d3cSFaisal Awada }
88f9b426b4SFaisal Awada if (!getFirmwarePath() || !isFirmwareFileValid())
89f9b426b4SFaisal Awada {
90f9b426b4SFaisal Awada return 1; // No firmware file abort download
91f9b426b4SFaisal Awada }
925ace9fb7SFaisal Awada bool downloadFwFailed = false; // Download Firmware status
935ace9fb7SFaisal Awada int retryProcessTwo(0);
945ace9fb7SFaisal Awada int retryProcessOne(0);
95*57fb664cSFaisal Awada disableEventLogging();
965ace9fb7SFaisal Awada while ((retryProcessTwo < MAX_RETRIES) && (retryProcessOne < MAX_RETRIES))
975a582d3cSFaisal Awada {
985ace9fb7SFaisal Awada // Write AEI PSU ISP key
995ace9fb7SFaisal Awada if (!writeIspKey())
1005ace9fb7SFaisal Awada {
1015ace9fb7SFaisal Awada lg2::error("Failed to set ISP Key");
1025ace9fb7SFaisal Awada downloadFwFailed = true; // Download Firmware status
103*57fb664cSFaisal Awada break;
1045a582d3cSFaisal Awada }
1055a582d3cSFaisal Awada
106*57fb664cSFaisal Awada if (retryProcessTwo == (MAX_RETRIES - 1))
107*57fb664cSFaisal Awada {
108*57fb664cSFaisal Awada enableEventLogging();
109*57fb664cSFaisal Awada }
110*57fb664cSFaisal Awada retryProcessTwo++;
1115ace9fb7SFaisal Awada while (retryProcessOne < MAX_RETRIES)
1125ace9fb7SFaisal Awada {
1135ace9fb7SFaisal Awada downloadFwFailed = false; // Download Firmware status
1145ace9fb7SFaisal Awada retryProcessOne++;
1155ace9fb7SFaisal Awada // Set ISP mode
1165ace9fb7SFaisal Awada if (!writeIspMode())
1175ace9fb7SFaisal Awada {
1185ace9fb7SFaisal Awada // Write ISP Mode failed MAX_RETRIES times
1195ace9fb7SFaisal Awada retryProcessTwo = MAX_RETRIES;
1205ace9fb7SFaisal Awada downloadFwFailed = true; // Download Firmware Failed
1215ace9fb7SFaisal Awada break;
1225ace9fb7SFaisal Awada }
1235ace9fb7SFaisal Awada
1245ace9fb7SFaisal Awada // Reset ISP status
1255ace9fb7SFaisal Awada if (writeIspStatusReset())
1265ace9fb7SFaisal Awada {
127*57fb664cSFaisal Awada // Start PSU firmware download.
1285ace9fb7SFaisal Awada if (downloadPsuFirmware())
1295ace9fb7SFaisal Awada {
1305ace9fb7SFaisal Awada if (!verifyDownloadFWStatus())
1315ace9fb7SFaisal Awada {
1325ace9fb7SFaisal Awada downloadFwFailed = true;
1335ace9fb7SFaisal Awada continue;
1345ace9fb7SFaisal Awada }
1355ace9fb7SFaisal Awada }
1365ace9fb7SFaisal Awada else
1375ace9fb7SFaisal Awada {
138*57fb664cSFaisal Awada // One of the block write commands failed, retry download
139*57fb664cSFaisal Awada // procedure one time starting with re-writing initial ISP
140*57fb664cSFaisal Awada // mode. If it fails again, log serviceable error.
141f9b426b4SFaisal Awada if (retryProcessOne == MAX_RETRIES)
142f9b426b4SFaisal Awada {
143*57fb664cSFaisal Awada // Callout PSU failed to update FW
144*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
145*57fb664cSFaisal Awada {"UPDATE_FAILED", "Download firmware failed"}};
146*57fb664cSFaisal Awada
147*57fb664cSFaisal Awada callOutPsuEventLog(additionalData);
148f9b426b4SFaisal Awada ispReboot(); // Try to set PSU to normal mode
149f9b426b4SFaisal Awada }
1505ace9fb7SFaisal Awada downloadFwFailed = true;
1515ace9fb7SFaisal Awada continue;
1525ace9fb7SFaisal Awada }
1535ace9fb7SFaisal Awada }
1545ace9fb7SFaisal Awada else
1555ace9fb7SFaisal Awada {
1565ace9fb7SFaisal Awada // ISP Status Reset failed MAX_RETRIES times
1575ace9fb7SFaisal Awada retryProcessTwo = MAX_RETRIES;
1585ace9fb7SFaisal Awada downloadFwFailed = true;
1595ace9fb7SFaisal Awada break;
1605ace9fb7SFaisal Awada }
1615ace9fb7SFaisal Awada
1625ace9fb7SFaisal Awada ispReboot();
163*57fb664cSFaisal Awada
1645ace9fb7SFaisal Awada if (ispReadRebootStatus() && !downloadFwFailed)
1655ace9fb7SFaisal Awada {
1665ace9fb7SFaisal Awada // Download completed successful
1675ace9fb7SFaisal Awada retryProcessTwo = MAX_RETRIES;
1685ace9fb7SFaisal Awada break;
1695ace9fb7SFaisal Awada }
1705ace9fb7SFaisal Awada else
1715ace9fb7SFaisal Awada {
172*57fb664cSFaisal Awada // Retry the whole download process starting with the key and
173*57fb664cSFaisal Awada // if fails again then report event log
1745ace9fb7SFaisal Awada if ((retryProcessOne < (MAX_RETRIES - 1)) &&
1755ace9fb7SFaisal Awada (retryProcessTwo < (MAX_RETRIES - 1)))
1765ace9fb7SFaisal Awada {
1775ace9fb7SFaisal Awada downloadFwFailed = false;
1785ace9fb7SFaisal Awada break;
1795ace9fb7SFaisal Awada }
1805ace9fb7SFaisal Awada }
1815ace9fb7SFaisal Awada }
1825ace9fb7SFaisal Awada }
1835ace9fb7SFaisal Awada if (downloadFwFailed)
1845a582d3cSFaisal Awada {
1855a582d3cSFaisal Awada return 1;
1865a582d3cSFaisal Awada }
187*57fb664cSFaisal Awada enableEventLogging();
188*57fb664cSFaisal Awada bindUnbind(true);
189*57fb664cSFaisal Awada updater::internal::delay(100);
190*57fb664cSFaisal Awada callOutGoodEventLog();
1915ace9fb7SFaisal Awada return 0; // Update successful
1925a582d3cSFaisal Awada }
1935a582d3cSFaisal Awada
writeIspKey()1945a582d3cSFaisal Awada bool AeiUpdater::writeIspKey()
1955a582d3cSFaisal Awada {
1965a582d3cSFaisal Awada // ISP Key to unlock programming mode ( ASCII for "artY").
1975a582d3cSFaisal Awada constexpr std::array<uint8_t, 4> unlockData = {0x61, 0x72, 0x74,
1985a582d3cSFaisal Awada 0x59}; // ISP Key "artY"
199*57fb664cSFaisal Awada for (int retry = 0; retry < MAX_RETRIES; ++retry)
200*57fb664cSFaisal Awada {
2015a582d3cSFaisal Awada try
2025a582d3cSFaisal Awada {
2035a582d3cSFaisal Awada // Send ISP Key to unlock device for firmware update
204*57fb664cSFaisal Awada i2cInterface->write(KEY_REGISTER, unlockData.size(),
205*57fb664cSFaisal Awada unlockData.data());
206*57fb664cSFaisal Awada disableEventLogging();
2075a582d3cSFaisal Awada return true;
2085a582d3cSFaisal Awada }
209*57fb664cSFaisal Awada catch (const i2c::I2CException& e)
2105a582d3cSFaisal Awada {
2115a582d3cSFaisal Awada // Log failure if I2C write fails.
2128dca5075SFaisal Awada lg2::error("I2C write failed: {ERROR}", "ERROR", e);
213*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
214*57fb664cSFaisal Awada {"I2C_ISP_KEY", "ISP key failed due to I2C exception"}};
215*57fb664cSFaisal Awada callOutI2CEventLog(additionalData, e.what(), e.errorCode);
216*57fb664cSFaisal Awada enableEventLogging(); // enable event logging if fail again call out
217*57fb664cSFaisal Awada // PSU & I2C
2185a582d3cSFaisal Awada }
219*57fb664cSFaisal Awada
220*57fb664cSFaisal Awada catch (const std::exception& e)
221*57fb664cSFaisal Awada {
222*57fb664cSFaisal Awada lg2::error("Exception write failed: {ERROR}", "ERROR", e);
223*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
224*57fb664cSFaisal Awada {"ISP_KEY", "ISP key failed due to exception"},
225*57fb664cSFaisal Awada {"EXCEPTION", e.what()}};
226*57fb664cSFaisal Awada callOutPsuEventLog(additionalData);
227*57fb664cSFaisal Awada enableEventLogging(); // enable Event Logging if fail again call out
228*57fb664cSFaisal Awada // PSU
229*57fb664cSFaisal Awada }
230*57fb664cSFaisal Awada }
231*57fb664cSFaisal Awada return false;
2325a582d3cSFaisal Awada }
2335a582d3cSFaisal Awada
writeIspMode()2345a582d3cSFaisal Awada bool AeiUpdater::writeIspMode()
2355a582d3cSFaisal Awada {
2365a582d3cSFaisal Awada // Attempt to set device in ISP mode with retries.
2375a582d3cSFaisal Awada uint8_t ispStatus = 0x0;
238*57fb664cSFaisal Awada uint8_t exceptionCount = 0;
2395a582d3cSFaisal Awada for (int retry = 0; retry < MAX_RETRIES; ++retry)
2405a582d3cSFaisal Awada {
2415a582d3cSFaisal Awada try
2425a582d3cSFaisal Awada {
2435a582d3cSFaisal Awada // Write command to enter ISP mode.
2445a582d3cSFaisal Awada i2cInterface->write(STATUS_REGISTER, CMD_BOOT_ISP);
2455a582d3cSFaisal Awada // Delay to allow status register update.
2465a582d3cSFaisal Awada updater::internal::delay(ISP_STATUS_DELAY);
2475a582d3cSFaisal Awada // Read back status register to confirm ISP mode is active.
2485a582d3cSFaisal Awada i2cInterface->read(STATUS_REGISTER, ispStatus);
2495a582d3cSFaisal Awada
2505a582d3cSFaisal Awada if (ispStatus & B_ISP_MODE)
2515a582d3cSFaisal Awada {
2525ace9fb7SFaisal Awada lg2::info("Set ISP Mode");
253*57fb664cSFaisal Awada disableEventLogging();
2545a582d3cSFaisal Awada return true;
2555a582d3cSFaisal Awada }
256*57fb664cSFaisal Awada enableEventLogging();
257*57fb664cSFaisal Awada }
258*57fb664cSFaisal Awada catch (const i2c::I2CException& e)
259*57fb664cSFaisal Awada {
260*57fb664cSFaisal Awada exceptionCount++;
261*57fb664cSFaisal Awada // Log I2C error with each retry attempt.
262*57fb664cSFaisal Awada lg2::error("I2C exception during ISP mode write/read: {ERROR}",
263*57fb664cSFaisal Awada "ERROR", e);
264*57fb664cSFaisal Awada if (exceptionCount == MAX_RETRIES)
265*57fb664cSFaisal Awada {
266*57fb664cSFaisal Awada enableEventLogging();
267*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
268*57fb664cSFaisal Awada {"I2C_FIRMWARE_STATUS",
269*57fb664cSFaisal Awada "Download firmware failed during writeIspMode due to I2C exception"}};
270*57fb664cSFaisal Awada // Callout PSU & I2C
271*57fb664cSFaisal Awada callOutI2CEventLog(additionalData, e.what(), e.errorCode);
272*57fb664cSFaisal Awada return false; // Failed to set ISP Mode
273*57fb664cSFaisal Awada }
2745a582d3cSFaisal Awada }
2755a582d3cSFaisal Awada catch (const std::exception& e)
2765a582d3cSFaisal Awada {
277*57fb664cSFaisal Awada exceptionCount++;
278*57fb664cSFaisal Awada // Log error with each retry attempt.
279*57fb664cSFaisal Awada lg2::error("Exception during ISP mode write/read: {ERROR}", "ERROR",
2808dca5075SFaisal Awada e);
281*57fb664cSFaisal Awada if (exceptionCount == MAX_RETRIES)
282*57fb664cSFaisal Awada {
283*57fb664cSFaisal Awada enableEventLogging();
284*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
285*57fb664cSFaisal Awada {"FIRMWARE_STATUS",
286*57fb664cSFaisal Awada "Download firmware failed during writeIspMode due to exception"},
287*57fb664cSFaisal Awada {"EXCEPTION", e.what()}};
288*57fb664cSFaisal Awada // Callout PSU
289*57fb664cSFaisal Awada callOutPsuEventLog(additionalData);
290*57fb664cSFaisal Awada return false; // Failed to set ISP Mode
2915a582d3cSFaisal Awada }
2925a582d3cSFaisal Awada }
293*57fb664cSFaisal Awada }
294*57fb664cSFaisal Awada
295*57fb664cSFaisal Awada if (exceptionCount != MAX_RETRIES)
296*57fb664cSFaisal Awada {
297*57fb664cSFaisal Awada // Callout PSU
298*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
299*57fb664cSFaisal Awada {"FIRMWARE_STATUS",
300*57fb664cSFaisal Awada "Download firmware failed during writeIspMode"}};
301*57fb664cSFaisal Awada callOutPsuEventLog(additionalData);
302*57fb664cSFaisal Awada }
303*57fb664cSFaisal Awada
3045a582d3cSFaisal Awada lg2::error("Failed to set ISP Mode");
3055a582d3cSFaisal Awada return false; // Failed to set ISP Mode after retries
3065a582d3cSFaisal Awada }
3075a582d3cSFaisal Awada
writeIspStatusReset()3085a582d3cSFaisal Awada bool AeiUpdater::writeIspStatusReset()
3095a582d3cSFaisal Awada {
3105a582d3cSFaisal Awada // Reset ISP status register before firmware download.
3115a582d3cSFaisal Awada uint8_t ispStatus = 0;
312*57fb664cSFaisal Awada uint8_t exceptionCount = 0;
3135ace9fb7SFaisal Awada for (int retry = 0; retry < MAX_RETRIES; retry++)
3145ace9fb7SFaisal Awada {
3155a582d3cSFaisal Awada try
3165a582d3cSFaisal Awada {
3175a582d3cSFaisal Awada i2cInterface->write(STATUS_REGISTER,
3185a582d3cSFaisal Awada CMD_RESET_SEQ); // Start reset sequence.
3195ace9fb7SFaisal Awada retry = MAX_RETRIES;
3205ace9fb7SFaisal Awada }
321*57fb664cSFaisal Awada catch (const i2c::I2CException& e)
3225ace9fb7SFaisal Awada {
323*57fb664cSFaisal Awada exceptionCount++;
3245ace9fb7SFaisal Awada // Log any errors encountered during reset sequence.
3255ace9fb7SFaisal Awada lg2::error("I2C Write ISP reset failed: {ERROR}", "ERROR", e);
326*57fb664cSFaisal Awada if (exceptionCount == MAX_RETRIES)
327*57fb664cSFaisal Awada {
328*57fb664cSFaisal Awada enableEventLogging();
329*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
330*57fb664cSFaisal Awada {"I2C_ISP_RESET", "I2C exception during ISP status reset"}};
331*57fb664cSFaisal Awada // Callout PSU & I2C
332*57fb664cSFaisal Awada callOutI2CEventLog(additionalData, e.what(), e.errorCode);
333*57fb664cSFaisal Awada ispReboot();
334*57fb664cSFaisal Awada return false;
335*57fb664cSFaisal Awada }
336*57fb664cSFaisal Awada }
337*57fb664cSFaisal Awada catch (const std::exception& e)
338*57fb664cSFaisal Awada {
339*57fb664cSFaisal Awada exceptionCount++;
340*57fb664cSFaisal Awada // Log any errors encountered during reset sequence.
341*57fb664cSFaisal Awada lg2::error("Write ISP reset failed: {ERROR}", "ERROR", e);
342*57fb664cSFaisal Awada if (exceptionCount == MAX_RETRIES)
343*57fb664cSFaisal Awada {
344*57fb664cSFaisal Awada enableEventLogging();
345*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
346*57fb664cSFaisal Awada {"ISP_RESET", "Exception during ISP status reset"},
347*57fb664cSFaisal Awada {"EXCEPTION", e.what()}};
348*57fb664cSFaisal Awada // Callout PSU
349*57fb664cSFaisal Awada callOutPsuEventLog(additionalData);
350*57fb664cSFaisal Awada ispReboot();
351*57fb664cSFaisal Awada return false;
352*57fb664cSFaisal Awada }
3535ace9fb7SFaisal Awada }
3545ace9fb7SFaisal Awada }
3555ace9fb7SFaisal Awada
356*57fb664cSFaisal Awada exceptionCount = 0;
3575a582d3cSFaisal Awada for (int retry = 0; retry < MAX_RETRIES; ++retry)
3585a582d3cSFaisal Awada {
3595ace9fb7SFaisal Awada try
3605ace9fb7SFaisal Awada {
3615a582d3cSFaisal Awada i2cInterface->read(STATUS_REGISTER, ispStatus);
3625a582d3cSFaisal Awada if (ispStatus == B_ISP_MODE)
3635a582d3cSFaisal Awada {
364*57fb664cSFaisal Awada lg2::info("write/read ISP reset");
365*57fb664cSFaisal Awada disableEventLogging();
3665a582d3cSFaisal Awada return true; // ISP status reset successfully.
3675a582d3cSFaisal Awada }
3685a582d3cSFaisal Awada i2cInterface->write(STATUS_REGISTER,
3695a582d3cSFaisal Awada CMD_CLEAR_STATUS); // Clear status if
3705a582d3cSFaisal Awada // not reset.
371*57fb664cSFaisal Awada lg2::error("Write ISP reset failed");
372*57fb664cSFaisal Awada enableEventLogging();
373*57fb664cSFaisal Awada }
374*57fb664cSFaisal Awada catch (const i2c::I2CException& e)
375*57fb664cSFaisal Awada {
376*57fb664cSFaisal Awada exceptionCount++;
377*57fb664cSFaisal Awada // Log any errors encountered during reset sequence.
378*57fb664cSFaisal Awada lg2::error(
379*57fb664cSFaisal Awada "I2C Write/Read or Write error during ISP reset: {ERROR}",
380*57fb664cSFaisal Awada "ERROR", e);
381*57fb664cSFaisal Awada if (exceptionCount == MAX_RETRIES)
382*57fb664cSFaisal Awada {
383*57fb664cSFaisal Awada enableEventLogging();
384*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
385*57fb664cSFaisal Awada {"I2C_ISP_READ_STATUS",
386*57fb664cSFaisal Awada "I2C exception during read ISP status"}};
387*57fb664cSFaisal Awada // Callout PSU & I2C
388*57fb664cSFaisal Awada callOutI2CEventLog(additionalData, e.what(), e.errorCode);
389*57fb664cSFaisal Awada }
3905a582d3cSFaisal Awada }
3915a582d3cSFaisal Awada catch (const std::exception& e)
3925a582d3cSFaisal Awada {
393*57fb664cSFaisal Awada exceptionCount++;
3945a582d3cSFaisal Awada // Log any errors encountered during reset sequence.
395*57fb664cSFaisal Awada lg2::error("Write/Read or Write error during ISP reset: {ERROR}",
3965ace9fb7SFaisal Awada "ERROR", e);
397*57fb664cSFaisal Awada if (exceptionCount == MAX_RETRIES)
398*57fb664cSFaisal Awada {
399*57fb664cSFaisal Awada enableEventLogging();
400*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
401*57fb664cSFaisal Awada {"ISP_READ_STATUS", "Exception during read ISP status"},
402*57fb664cSFaisal Awada {"EXCEPTION", e.what()}};
403*57fb664cSFaisal Awada // Callout PSU
404*57fb664cSFaisal Awada callOutPsuEventLog(additionalData);
4055ace9fb7SFaisal Awada }
4065a582d3cSFaisal Awada }
407*57fb664cSFaisal Awada }
408*57fb664cSFaisal Awada if (exceptionCount != MAX_RETRIES)
409*57fb664cSFaisal Awada {
410*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
411*57fb664cSFaisal Awada {"ISP_REST_FAILED", "Failed to read ISP expected status"}};
412*57fb664cSFaisal Awada // Callout PSU
413*57fb664cSFaisal Awada callOutPsuEventLog(additionalData);
414*57fb664cSFaisal Awada }
4155a582d3cSFaisal Awada lg2::error("Failed to reset ISP Status");
4165ace9fb7SFaisal Awada ispReboot();
4175a582d3cSFaisal Awada return false;
4185a582d3cSFaisal Awada }
4195a582d3cSFaisal Awada
getFirmwarePath()420f9b426b4SFaisal Awada bool AeiUpdater::getFirmwarePath()
4218dca5075SFaisal Awada {
422f9b426b4SFaisal Awada fspath = updater::internal::getFWFilenamePath(getImageDir());
4238dca5075SFaisal Awada if (fspath.empty())
4248dca5075SFaisal Awada {
425*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
426*57fb664cSFaisal Awada {"FILE_PATH", "Firmware file path is null"}};
427*57fb664cSFaisal Awada // Callout BMC0001 procedure
428*57fb664cSFaisal Awada callOutSWEventLog(additionalData);
4298dca5075SFaisal Awada lg2::error("Firmware file path not found");
4308dca5075SFaisal Awada return false;
4318dca5075SFaisal Awada }
4328dca5075SFaisal Awada return true;
4338dca5075SFaisal Awada }
4348dca5075SFaisal Awada
isFirmwareFileValid()435f9b426b4SFaisal Awada bool AeiUpdater::isFirmwareFileValid()
436f9b426b4SFaisal Awada {
437f9b426b4SFaisal Awada if (!updater::internal::validateFWFile(fspath))
438f9b426b4SFaisal Awada {
439*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
440*57fb664cSFaisal Awada {"FIRMWARE_VALID",
441*57fb664cSFaisal Awada "Firmware validation failed, FW file path = " + fspath}};
442*57fb664cSFaisal Awada // Callout BMC0001 procedure
443*57fb664cSFaisal Awada callOutSWEventLog(additionalData);
444f9b426b4SFaisal Awada lg2::error("Firmware validation failed, fspath={PATH}", "PATH", fspath);
445f9b426b4SFaisal Awada return false;
446f9b426b4SFaisal Awada }
447f9b426b4SFaisal Awada return true;
448f9b426b4SFaisal Awada }
449f9b426b4SFaisal Awada
openFirmwareFile()450f9b426b4SFaisal Awada std::unique_ptr<std::ifstream> AeiUpdater::openFirmwareFile()
4518dca5075SFaisal Awada {
4528dca5075SFaisal Awada auto inputFile = updater::internal::openFirmwareFile(fspath);
4538dca5075SFaisal Awada if (!inputFile)
4548dca5075SFaisal Awada {
455*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
456*57fb664cSFaisal Awada {"FIRMWARE_OPEN",
457*57fb664cSFaisal Awada "Firmware file failed to open, FW file path = " + fspath}};
458*57fb664cSFaisal Awada // Callout BMC0001 procedure
459*57fb664cSFaisal Awada callOutSWEventLog(additionalData);
4608dca5075SFaisal Awada lg2::error("Failed to open firmware file");
4618dca5075SFaisal Awada }
4628dca5075SFaisal Awada return inputFile;
4638dca5075SFaisal Awada }
4648dca5075SFaisal Awada
readFirmwareBlock(std::ifstream & file,const size_t & bytesToRead)4658dca5075SFaisal Awada std::vector<uint8_t> AeiUpdater::readFirmwareBlock(std::ifstream& file,
4668dca5075SFaisal Awada const size_t& bytesToRead)
4678dca5075SFaisal Awada {
4688dca5075SFaisal Awada auto block = updater::internal::readFirmwareBytes(file, bytesToRead);
4698dca5075SFaisal Awada return block;
4708dca5075SFaisal Awada }
4718dca5075SFaisal Awada
prepareCommandBlock(const std::vector<uint8_t> & dataBlockRead)4725ace9fb7SFaisal Awada void AeiUpdater::prepareCommandBlock(const std::vector<uint8_t>& dataBlockRead)
4738dca5075SFaisal Awada {
4745ace9fb7SFaisal Awada cmdBlockWrite.clear(); // Clear cmdBlockWrite before use
4755ace9fb7SFaisal Awada // Assign new values to cmdBlockWrite
4765ace9fb7SFaisal Awada cmdBlockWrite.push_back(ISP_MEMORY_REGISTER);
4775ace9fb7SFaisal Awada cmdBlockWrite.push_back(BLOCK_WRITE_SIZE);
4788dca5075SFaisal Awada cmdBlockWrite.insert(cmdBlockWrite.end(), byteSwappedIndex.begin(),
4798dca5075SFaisal Awada byteSwappedIndex.end());
4808dca5075SFaisal Awada cmdBlockWrite.insert(cmdBlockWrite.end(), dataBlockRead.begin(),
4818dca5075SFaisal Awada dataBlockRead.end());
4828dca5075SFaisal Awada
4838dca5075SFaisal Awada // Resize to ensure it matches BLOCK_WRITE_SIZE + 1 and append CRC
4848dca5075SFaisal Awada if (cmdBlockWrite.size() != BLOCK_WRITE_SIZE + 1)
4858dca5075SFaisal Awada {
4868dca5075SFaisal Awada cmdBlockWrite.resize(BLOCK_WRITE_SIZE + 1, 0xFF);
4878dca5075SFaisal Awada }
4888dca5075SFaisal Awada cmdBlockWrite.push_back(updater::internal::calculateCRC8(cmdBlockWrite));
4898dca5075SFaisal Awada // Remove the F9 and byte count
4908dca5075SFaisal Awada cmdBlockWrite.erase(cmdBlockWrite.begin(), cmdBlockWrite.begin() + 2);
4915ace9fb7SFaisal Awada }
4928dca5075SFaisal Awada
downloadPsuFirmware()4935ace9fb7SFaisal Awada bool AeiUpdater::downloadPsuFirmware()
4945ace9fb7SFaisal Awada {
4955ace9fb7SFaisal Awada // Open firmware file
496f9b426b4SFaisal Awada auto inputFile = openFirmwareFile();
4975ace9fb7SFaisal Awada if (!inputFile)
4985ace9fb7SFaisal Awada {
499*57fb664cSFaisal Awada if (isEventLogEnabled())
500*57fb664cSFaisal Awada {
501*57fb664cSFaisal Awada // Callout BMC0001 procedure
502*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
503*57fb664cSFaisal Awada {"FW_FAILED_TO_OPEN", "Firmware file failed to open"},
504*57fb664cSFaisal Awada {"FW_FILE_PATH", fspath}};
505*57fb664cSFaisal Awada
506*57fb664cSFaisal Awada callOutSWEventLog(additionalData);
507*57fb664cSFaisal Awada ispReboot(); // Try to set PSU to normal mode
508*57fb664cSFaisal Awada }
5095ace9fb7SFaisal Awada lg2::error("Unable to open firmware file {FILE}", "FILE", fspath);
5105ace9fb7SFaisal Awada return false;
5115ace9fb7SFaisal Awada }
5125ace9fb7SFaisal Awada
5135ace9fb7SFaisal Awada // Read and process firmware file in blocks
5145ace9fb7SFaisal Awada size_t bytesRead = 0;
5155ace9fb7SFaisal Awada const auto fileSize = std::filesystem::file_size(fspath);
5165ace9fb7SFaisal Awada bool downloadFailed = false;
5175ace9fb7SFaisal Awada byteSwappedIndex =
5185ace9fb7SFaisal Awada updater::internal::bigEndianToLittleEndian(START_SEQUENCE_INDEX);
5195ace9fb7SFaisal Awada int writeBlockDelay = MEM_WRITE_DELAY;
5205ace9fb7SFaisal Awada
5215ace9fb7SFaisal Awada while ((bytesRead < fileSize) && !downloadFailed)
5225ace9fb7SFaisal Awada {
5235ace9fb7SFaisal Awada // Read a block of firmware data
5245ace9fb7SFaisal Awada auto dataRead = readFirmwareBlock(*inputFile, FW_READ_BLOCK_SIZE);
5255ace9fb7SFaisal Awada bytesRead += dataRead.size();
5265ace9fb7SFaisal Awada
5275ace9fb7SFaisal Awada // Prepare command block with the current index and data
5285ace9fb7SFaisal Awada prepareCommandBlock(dataRead);
5295ace9fb7SFaisal Awada
5305ace9fb7SFaisal Awada // Perform I2C write/read with retries
5315ace9fb7SFaisal Awada uint8_t readData[I2C_SMBUS_BLOCK_MAX] = {};
5325ace9fb7SFaisal Awada downloadFailed = !performI2cWriteReadWithRetries(
5335ace9fb7SFaisal Awada ISP_MEMORY_REGISTER, EXPECTED_MEM_READ_REPLY, readData, MAX_RETRIES,
5345ace9fb7SFaisal Awada writeBlockDelay);
5355ace9fb7SFaisal Awada
5365ace9fb7SFaisal Awada // Adjust delay after first write block
5375ace9fb7SFaisal Awada writeBlockDelay = MEM_STRETCH_DELAY;
5385ace9fb7SFaisal Awada }
5395ace9fb7SFaisal Awada
5405ace9fb7SFaisal Awada inputFile->close();
5415ace9fb7SFaisal Awada
5425ace9fb7SFaisal Awada // Log final download status
5435ace9fb7SFaisal Awada if (downloadFailed)
5445ace9fb7SFaisal Awada {
5455ace9fb7SFaisal Awada lg2::error(
5465ace9fb7SFaisal Awada "Firmware download failed after retries at FW block {BYTESREAD}",
5475ace9fb7SFaisal Awada "BYTESREAD", bytesRead);
5485ace9fb7SFaisal Awada return false; // Failed
5495ace9fb7SFaisal Awada }
5505ace9fb7SFaisal Awada return true;
5515ace9fb7SFaisal Awada }
5525ace9fb7SFaisal Awada
performI2cWriteReadWithRetries(uint8_t regAddr,const uint8_t expectedReadSize,uint8_t * readData,const int retries,const int delayTime)5535ace9fb7SFaisal Awada bool AeiUpdater::performI2cWriteReadWithRetries(
5545ace9fb7SFaisal Awada uint8_t regAddr, const uint8_t expectedReadSize, uint8_t* readData,
5555ace9fb7SFaisal Awada const int retries, const int delayTime)
5565ace9fb7SFaisal Awada {
557*57fb664cSFaisal Awada uint8_t exceptionCount = 0;
558*57fb664cSFaisal Awada uint32_t bigEndianValue = 0;
5595ace9fb7SFaisal Awada for (int i = 0; i < retries; ++i)
5605ace9fb7SFaisal Awada {
5615ace9fb7SFaisal Awada uint8_t readReplySize = 0;
5625ace9fb7SFaisal Awada try
5635ace9fb7SFaisal Awada {
5645ace9fb7SFaisal Awada performI2cWriteRead(regAddr, readReplySize, readData, delayTime);
565f9b426b4SFaisal Awada if ((readData[STATUS_CML_INDEX] == 0 ||
566f9b426b4SFaisal Awada // The first firmware data packet sent to the PSU have a
567f9b426b4SFaisal Awada // response of 0x80 which indicates firmware update in
568f9b426b4SFaisal Awada // progress. If retry to send the first packet again reply will
569f9b426b4SFaisal Awada // be 0.
570f9b426b4SFaisal Awada (readData[STATUS_CML_INDEX] == 0x80 &&
571f9b426b4SFaisal Awada delayTime == MEM_WRITE_DELAY)) &&
5725ace9fb7SFaisal Awada (readReplySize == expectedReadSize) &&
5735ace9fb7SFaisal Awada !std::equal(readData, readData + 4, byteSwappedIndex.begin()))
5745ace9fb7SFaisal Awada {
5755ace9fb7SFaisal Awada std::copy(readData, readData + 4, byteSwappedIndex.begin());
5765ace9fb7SFaisal Awada return true;
5775ace9fb7SFaisal Awada }
5785ace9fb7SFaisal Awada else
5795ace9fb7SFaisal Awada {
580*57fb664cSFaisal Awada bigEndianValue = (readData[0] << 24) | (readData[1] << 16) |
581*57fb664cSFaisal Awada (readData[2] << 8) | (readData[3]);
582f9b426b4SFaisal Awada lg2::error("Write/read block {NUM} failed", "NUM",
583f9b426b4SFaisal Awada bigEndianValue);
5845ace9fb7SFaisal Awada }
5855ace9fb7SFaisal Awada }
586*57fb664cSFaisal Awada catch (const i2c::I2CException& e)
587*57fb664cSFaisal Awada {
588*57fb664cSFaisal Awada exceptionCount++;
589*57fb664cSFaisal Awada if (exceptionCount == MAX_RETRIES)
590*57fb664cSFaisal Awada {
591*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
592*57fb664cSFaisal Awada {"I2C_WRITE_READ",
593*57fb664cSFaisal Awada "I2C exception while flashing the firmware."}};
594*57fb664cSFaisal Awada // Callout PSU & I2C
595*57fb664cSFaisal Awada callOutI2CEventLog(additionalData, e.what(), e.errorCode);
596*57fb664cSFaisal Awada }
597*57fb664cSFaisal Awada lg2::error("I2C exception write/read block failed: {ERROR}",
598*57fb664cSFaisal Awada "ERROR", e.what());
599*57fb664cSFaisal Awada }
6005ace9fb7SFaisal Awada catch (const std::exception& e)
6015ace9fb7SFaisal Awada {
602*57fb664cSFaisal Awada exceptionCount++;
603*57fb664cSFaisal Awada if (exceptionCount == MAX_RETRIES)
604*57fb664cSFaisal Awada {
605*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
606*57fb664cSFaisal Awada {"WRITE_READ", "Exception while flashing the firmware."},
607*57fb664cSFaisal Awada {"EXCEPTION", e.what()}};
608*57fb664cSFaisal Awada // Callout PSU
609*57fb664cSFaisal Awada callOutPsuEventLog(additionalData);
610*57fb664cSFaisal Awada }
611*57fb664cSFaisal Awada lg2::error("Exception write/read block failed: {ERROR}", "ERROR",
612*57fb664cSFaisal Awada e.what());
6135ace9fb7SFaisal Awada }
6145ace9fb7SFaisal Awada }
615*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
616*57fb664cSFaisal Awada {"WRITE_READ",
617*57fb664cSFaisal Awada "Download firmware failed block: " + std::to_string(bigEndianValue)}};
618*57fb664cSFaisal Awada // Callout PSU
619*57fb664cSFaisal Awada callOutPsuEventLog(additionalData);
6205ace9fb7SFaisal Awada return false;
6215ace9fb7SFaisal Awada }
6225ace9fb7SFaisal Awada
performI2cWriteRead(uint8_t regAddr,uint8_t & readReplySize,uint8_t * readData,const int & delayTime)6235ace9fb7SFaisal Awada void AeiUpdater::performI2cWriteRead(uint8_t regAddr, uint8_t& readReplySize,
6245ace9fb7SFaisal Awada uint8_t* readData, const int& delayTime)
6255ace9fb7SFaisal Awada {
6265ace9fb7SFaisal Awada i2cInterface->processCall(regAddr, cmdBlockWrite.size(),
6275ace9fb7SFaisal Awada cmdBlockWrite.data(), readReplySize, readData);
6285ace9fb7SFaisal Awada
6295ace9fb7SFaisal Awada if (delayTime != 0)
6305ace9fb7SFaisal Awada {
6315ace9fb7SFaisal Awada updater::internal::delay(delayTime);
6325ace9fb7SFaisal Awada }
6335ace9fb7SFaisal Awada }
6345ace9fb7SFaisal Awada
verifyDownloadFWStatus()6355ace9fb7SFaisal Awada bool AeiUpdater::verifyDownloadFWStatus()
6365ace9fb7SFaisal Awada {
6375ace9fb7SFaisal Awada try
6385ace9fb7SFaisal Awada {
6395ace9fb7SFaisal Awada // Read and verify firmware download status.
6405ace9fb7SFaisal Awada uint8_t status = 0;
6415ace9fb7SFaisal Awada i2cInterface->read(STATUS_REGISTER, status);
6425ace9fb7SFaisal Awada if (status != B_ISP_MODE_CHKSUM_GOOD)
6435ace9fb7SFaisal Awada {
6445ace9fb7SFaisal Awada lg2::error("Firmware download failed - status: {ERR}", "ERR",
6455ace9fb7SFaisal Awada status);
6465ace9fb7SFaisal Awada
6475ace9fb7SFaisal Awada return false; // Failed checksum
6485ace9fb7SFaisal Awada }
6495ace9fb7SFaisal Awada return true;
6505ace9fb7SFaisal Awada }
6515ace9fb7SFaisal Awada catch (const std::exception& e)
6525ace9fb7SFaisal Awada {
6535ace9fb7SFaisal Awada lg2::error("I2C read status register failed: {ERROR}", "ERROR", e);
6545ace9fb7SFaisal Awada }
6555ace9fb7SFaisal Awada return false; // Failed
6568dca5075SFaisal Awada }
6578dca5075SFaisal Awada
ispReboot()6588dca5075SFaisal Awada void AeiUpdater::ispReboot()
6598dca5075SFaisal Awada {
6608dca5075SFaisal Awada updater::internal::delay(
6618dca5075SFaisal Awada MEM_COMPLETE_DELAY); // Delay before starting the reboot process
6628dca5075SFaisal Awada
6638dca5075SFaisal Awada try
6648dca5075SFaisal Awada {
6658dca5075SFaisal Awada // Write reboot command to the status register
6668dca5075SFaisal Awada i2cInterface->write(STATUS_REGISTER, CMD_BOOT_PWR);
6678dca5075SFaisal Awada
6688dca5075SFaisal Awada updater::internal::delay(
6698dca5075SFaisal Awada REBOOT_DELAY); // Add delay after writing reboot command
6708dca5075SFaisal Awada }
6718dca5075SFaisal Awada catch (const std::exception& e)
6728dca5075SFaisal Awada {
6738dca5075SFaisal Awada lg2::error("I2C write error during reboot: {ERROR}", "ERROR", e);
6748dca5075SFaisal Awada }
6758dca5075SFaisal Awada }
6768dca5075SFaisal Awada
ispReadRebootStatus()6778dca5075SFaisal Awada bool AeiUpdater::ispReadRebootStatus()
6788dca5075SFaisal Awada {
679*57fb664cSFaisal Awada for (int retry = 0; retry < MAX_RETRIES; ++retry)
680*57fb664cSFaisal Awada {
6818dca5075SFaisal Awada try
6828dca5075SFaisal Awada {
6838dca5075SFaisal Awada // Read from the status register to verify reboot
6848dca5075SFaisal Awada uint8_t data = 1; // Initialize data to a non-zero value
6858dca5075SFaisal Awada i2cInterface->read(STATUS_REGISTER, data);
6868dca5075SFaisal Awada
6878dca5075SFaisal Awada // If the reboot was successful, the read data should be 0
6885ace9fb7SFaisal Awada if (data == SUCCESSFUL_ISP_REBOOT_STATUS)
6898dca5075SFaisal Awada {
6908dca5075SFaisal Awada lg2::info("ISP Status Reboot successful.");
6918dca5075SFaisal Awada return true;
6928dca5075SFaisal Awada }
6938dca5075SFaisal Awada }
694*57fb664cSFaisal Awada catch (const i2c::I2CException& e)
695*57fb664cSFaisal Awada {
696*57fb664cSFaisal Awada if (isEventLogEnabled())
697*57fb664cSFaisal Awada {
698*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
699*57fb664cSFaisal Awada {"I2C_READ_REBOOT",
700*57fb664cSFaisal Awada "I2C exception while reading ISP reboot status"}};
701*57fb664cSFaisal Awada
702*57fb664cSFaisal Awada // Callout PSU & I2C
703*57fb664cSFaisal Awada callOutI2CEventLog(additionalData, e.what(), e.errorCode);
704*57fb664cSFaisal Awada }
705*57fb664cSFaisal Awada lg2::error("I2C read error during reboot attempt: {ERROR}", "ERROR",
706*57fb664cSFaisal Awada e);
707*57fb664cSFaisal Awada }
7088dca5075SFaisal Awada catch (const std::exception& e)
7098dca5075SFaisal Awada {
710*57fb664cSFaisal Awada if (isEventLogEnabled())
711*57fb664cSFaisal Awada {
712*57fb664cSFaisal Awada std::map<std::string, std::string> additionalData = {
713*57fb664cSFaisal Awada {"READ_REBOOT",
714*57fb664cSFaisal Awada "Exception while reading ISP reboot status"},
715*57fb664cSFaisal Awada {"EXCEPTION", e.what()}};
716*57fb664cSFaisal Awada
717*57fb664cSFaisal Awada // Callout PSU
718*57fb664cSFaisal Awada callOutPsuEventLog(additionalData);
719*57fb664cSFaisal Awada }
720*57fb664cSFaisal Awada lg2::error("Read exception during reboot attempt: {ERROR}", "ERROR",
721*57fb664cSFaisal Awada e);
722*57fb664cSFaisal Awada }
723*57fb664cSFaisal Awada // Reboot the PSU
724*57fb664cSFaisal Awada ispReboot(); // Try to set PSU to normal mode
7258dca5075SFaisal Awada }
7265ace9fb7SFaisal Awada
7275ace9fb7SFaisal Awada // If we reach here, all retries have failed
7285ace9fb7SFaisal Awada lg2::error("Failed to reboot ISP status after max retries.");
7298dca5075SFaisal Awada return false;
7308dca5075SFaisal Awada }
7315a582d3cSFaisal Awada } // namespace aeiUpdater
732