From 6e49b77b08307118a491e24b7c2c328b69ec4c0c Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 3 Nov 2021 17:17:24 +0100 Subject: [PATCH] updating kernel like program fpga, execute command to print which module failed, unlinking temporary file while programming bug fix --- RELEASE.txt | 4 +- python/src/detector.cpp | 5 +- .../include/slsDetectorServer_funcs.h | 3 +- .../src/slsDetectorServer_funcs.c | 138 +++++++++++++++ slsDetectorSoftware/include/sls/Detector.h | 8 + slsDetectorSoftware/src/CmdProxy.cpp | 23 ++- slsDetectorSoftware/src/CmdProxy.h | 2 + slsDetectorSoftware/src/Detector.cpp | 8 +- slsDetectorSoftware/src/DetectorImpl.cpp | 66 ++++++- slsDetectorSoftware/src/DetectorImpl.h | 11 +- slsDetectorSoftware/src/Module.cpp | 161 ++++++++++++++++-- slsDetectorSoftware/src/Module.h | 5 +- slsDetectorSoftware/tests/test-CmdProxy.cpp | 19 +++ .../include/sls/sls_detector_funcs.h | 2 + 14 files changed, 435 insertions(+), 20 deletions(-) diff --git a/RELEASE.txt b/RELEASE.txt index e0f1d3af7..7fcaf65d0 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -20,7 +20,7 @@ This document describes the differences between vx.x.x and v6.0.0. 1. New or Changed Features ========================== - kernelversion - +- updatekernel 2. Resolved Issues @@ -30,6 +30,8 @@ This document describes the differences between vx.x.x and v6.0.0. - rx id in config file was not taken into account. fixed. - programming firmware failure for blackfin, fixed but requires new kernel. - nios kernel check updated (ensuring right kernel) +- executecommand now says which module failed +- programming firmware did not delete temporary file created. fixed. 3. Known Issues =============== diff --git a/python/src/detector.cpp b/python/src/detector.cpp index c25c807de..da7a6ad91 100644 --- a/python/src/detector.cpp +++ b/python/src/detector.cpp @@ -1520,7 +1520,10 @@ void init_det(py::module &m) { (void (Detector::*)(const std::string &, const std::string &, sls::Positions)) & Detector::copyDetectorServer, - py::arg(), py::arg(), py::arg() = Positions{}) + .def("updateKernel", + (void (Detector::*)(const std::string &, sls::Positions)) & + Detector::updateKernel, + py::arg(), py::arg() = Positions{}) .def("rebootController", (void (Detector::*)(sls::Positions)) & Detector::rebootController, py::arg() = Positions{}) diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h index a6026dd72..c1201186d 100644 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h @@ -277,4 +277,5 @@ int get_udp_first_dest(int); int set_udp_first_dest(int); int get_readout_speed(int); int set_readout_speed(int); -int get_kernel_version(int); \ No newline at end of file +int get_kernel_version(int); +int copy_kernel(int); \ No newline at end of file diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index 086e6380e..539e08d28 100644 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -415,6 +415,8 @@ void function_table() { flist[F_GET_READOUT_SPEED] = &get_readout_speed; flist[F_SET_READOUT_SPEED] = &set_readout_speed; flist[F_GET_KERNEL_VERSION] = &get_kernel_version; + flist[F_COPY_KERNEL] = ©_kernel; + // check if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) { @@ -9434,3 +9436,139 @@ int get_kernel_version(int file_des) { } return Server_SendResult(file_des, OTHER, retvals, sizeof(retvals)); } + + +int copy_kernel(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); + char args[2][MAX_STR_LENGTH]; + char retvals[MAX_STR_LENGTH] = {0}; + + memset(args, 0, sizeof(args)); + memset(retvals, 0, sizeof(retvals)); + + if (receiveData(file_des, args, sizeof(args), OTHER) < 0) + return printSocketReadError(); + +#ifdef VIRTUAL + functionNotImplemented(); +#else + + // only set + if (Server_VerifyLock() == OK) { + char *sname = args[0]; + char *hostname = args[1]; + LOG(logINFOBLUE, ("Copying kernel image %s from host %s\n", sname, hostname)); + char cmd[MAX_STR_LENGTH] = {0}; + + // tftp server + char *format = "tftp %s -r %s -g"; + if (snprintf(cmd, MAX_STR_LENGTH, format, hostname, sname) >= + MAX_STR_LENGTH) { + ret = FAIL; + strcpy(mess, "Could not copy detector server. Command to copy " + "server too long\n"); + LOG(logERROR, (mess)); + } else if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + ret = FAIL; + snprintf(mess, MAX_STR_LENGTH, + "Could not copy detector server (tftp). %s\n", retvals); + // LOG(logERROR, (mess)); already printed in executecommand + } else { + LOG(logINFO, ("\tServer copied\n")); + } + + // give permissions + if (ret == OK) { + if (snprintf(cmd, MAX_STR_LENGTH, "chmod 777 %s", sname) >= + MAX_STR_LENGTH) { + ret = FAIL; + strcpy(mess, "Could not copy detector server. Command to give " + "permissions to server is too long\n"); + LOG(logERROR, (mess)); + } else if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + ret = FAIL; + snprintf(mess, MAX_STR_LENGTH, + "Could not copy detector server (permissions). %s\n", + retvals); + // LOG(logERROR, (mess)); already printed in executecommand + } else { + LOG(logINFO, ("\tPermissions modified\n")); + } + } + + // symbolic link + if (ret == OK) { + if (snprintf(cmd, MAX_STR_LENGTH, "ln -sf %s %s", sname, + LINKED_SERVER_NAME) >= MAX_STR_LENGTH) { + ret = FAIL; + strcpy(mess, "Could not copy detector server. Command to " + "create symbolic link too long\n"); + LOG(logERROR, (mess)); + } else if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + ret = FAIL; + snprintf(mess, MAX_STR_LENGTH, + "Could not copy detector server (symbolic link). %s\n", + retvals); + // LOG(logERROR, (mess)); already printed in executecommand + } else { + LOG(logINFO, ("\tSymbolic link created\n")); + } + } + + // blackfin boards (respawn) (only kept for backwards compatibility) +#if defined(JUNGFRAUD) || defined(CHIPTESTBOARDD) || defined(MOENCHD) || \ + defined(GOTTHARDD) + // delete every line with DetectorServer in /etc/inittab + if (ret == OK) { + strcpy(cmd, "sed -i '/DetectorServer/d' /etc/inittab"); + if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + ret = FAIL; + snprintf( + mess, MAX_STR_LENGTH, + "Could not copy detector server (del respawning). %s\n", + retvals); + // LOG(logERROR, (mess)); already printed in executecommand + } else { + LOG(logINFO, ("\tinittab: DetectoServer line deleted\n")); + } + } + + // add new link name to /etc/inittab + if (ret == OK) { + format = "echo 'ttyS0::respawn:/./%s' >> /etc/inittab"; + if (snprintf(cmd, MAX_STR_LENGTH, format, LINKED_SERVER_NAME) >= + MAX_STR_LENGTH) { + ret = FAIL; + strcpy(mess, "Could not copy detector server. Command " + "to add new server for spawning is too long\n"); + LOG(logERROR, (mess)); + } else if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + ret = FAIL; + snprintf(mess, MAX_STR_LENGTH, + "Could not copy detector server (respawning). %s\n", + retvals); + // LOG(logERROR, (mess)); already printed in executecommand + } else { + LOG(logINFO, ("\tinittab: updated for respawning\n")); + } + } +#endif + + // sync + if (ret == OK) { + strcpy(cmd, "sync"); + if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) { + ret = FAIL; + snprintf(mess, MAX_STR_LENGTH, + "Could not copy detector server (sync). %s\n", + retvals); + // LOG(logERROR, (mess)); already printed in executecommand + } else { + LOG(logINFO, ("\tsync\n")); + } + } + } +#endif + return Server_SendResult(file_des, OTHER, retvals, sizeof(retvals)); +} \ No newline at end of file diff --git a/slsDetectorSoftware/include/sls/Detector.h b/slsDetectorSoftware/include/sls/Detector.h index 451038412..43866df54 100644 --- a/slsDetectorSoftware/include/sls/Detector.h +++ b/slsDetectorSoftware/include/sls/Detector.h @@ -1744,6 +1744,14 @@ class Detector { void copyDetectorServer(const std::string &fname, const std::string &hostname, Positions pos = {}); + /** [Jungfrau][Ctb][Moench][Mythen3][Gotthard2] \n + * Advanced Command!! You could damage the detector. Please use with + * caution.\nUpdates the kernel image. Then, detector controller reboots + * with new kernel + */ + void updateKernel(const std::string &fname, Positions pos = {}); + + /** [Jungfrau][Gotthard][CTB][Moench][Mythen3][Gotthard2] Advanced user * Function! */ void rebootController(Positions pos = {}); diff --git a/slsDetectorSoftware/src/CmdProxy.cpp b/slsDetectorSoftware/src/CmdProxy.cpp index 5ecf8f281..9f5d554cd 100644 --- a/slsDetectorSoftware/src/CmdProxy.cpp +++ b/slsDetectorSoftware/src/CmdProxy.cpp @@ -2853,7 +2853,7 @@ std::string CmdProxy::CopyDetectorServer(int action) { "[pc_host_name]\n\t[Jungfrau][Eiger][Ctb][Moench][Mythen3][" "Gotthard2] Copies detector server via tftp from pc. Ensure that " "server is in the pc's tftp folder. Makes a symbolic link with a " - "shorter name (without vx.x.x). Then, detector reboots (except " + "shorter name (without vx.x.x). Then, detector controller reboots (except " "Eiger).\n\t[Jungfrau][Ctb][Moench]Also changes respawn server " "to the link, which is effective after a reboot." << '\n'; @@ -2871,6 +2871,27 @@ std::string CmdProxy::CopyDetectorServer(int action) { return os.str(); } +std::string CmdProxy::UpdateKernel(int action) { + std::ostringstream os; + os << cmd << ' '; + if (action == defs::HELP_ACTION) { + os << "[kernel_name with full path]\n\t[Jungfrau][Ctb][Moench][Mythen3][" + "Gotthard2] Advanced Command!! You could damage the detector. Please use" "with caution.\n\tUpdates the kernel image. Then, detector controller " "reboots with new kernel." + << '\n'; + } else if (action == defs::GET_ACTION) { + throw sls::RuntimeError("Cannot get"); + } else if (action == defs::PUT_ACTION) { + if (args.size() != 1) { + WrongNumberOfParameters(1); + } + det->updateKernel(args[0], std::vector{det_id}); + os << "successful\n"; + } else { + throw sls::RuntimeError("Unknown action"); + } + return os.str(); +} + std::string CmdProxy::UpdateFirmwareAndDetectorServer(int action) { std::ostringstream os; os << cmd << ' '; diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index 0e9fdfa5d..c52020afa 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -1059,6 +1059,7 @@ class CmdProxy { {"programfpga", &CmdProxy::ProgramFpga}, {"resetfpga", &CmdProxy::resetfpga}, {"copydetectorserver", &CmdProxy::CopyDetectorServer}, + {"updatekernel", &CmdProxy::UpdateKernel}, {"rebootcontroller", &CmdProxy::rebootcontroller}, {"update", &CmdProxy::UpdateFirmwareAndDetectorServer}, {"reg", &CmdProxy::Register}, @@ -1183,6 +1184,7 @@ class CmdProxy { /* Advanced */ std::string ProgramFpga(int action); std::string CopyDetectorServer(int action); + std::string UpdateKernel(int action); std::string UpdateFirmwareAndDetectorServer(int action); std::string Register(int action); std::string AdcRegister(int action); diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index bfa62f1f6..7b5258df7 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -2150,6 +2150,12 @@ void Detector::copyDetectorServer(const std::string &fname, } } +void Detector::updateKernel(const std::string &fname, Positions pos) { + std::vector buffer = pimpl->readKernelFile(fname); + pimpl->Parallel(&Module::updateKernel, pos, buffer); + rebootController(pos); +} + void Detector::rebootController(Positions pos) { pimpl->Parallel(&Module::rebootController, pos); } @@ -2240,7 +2246,7 @@ Result Detector::getLastClientIP(Positions pos) const { Result Detector::executeCommand(const std::string &value, Positions pos) { - return pimpl->Parallel(&Module::execCommand, pos, value); + return pimpl->Parallel(&Module::executeCommand, pos, value); } Result Detector::getNumberOfFramesFromStart(Positions pos) const { diff --git a/slsDetectorSoftware/src/DetectorImpl.cpp b/slsDetectorSoftware/src/DetectorImpl.cpp index f9aa1a1ab..b3322fc0e 100644 --- a/slsDetectorSoftware/src/DetectorImpl.cpp +++ b/slsDetectorSoftware/src/DetectorImpl.cpp @@ -1386,8 +1386,70 @@ std::vector DetectorImpl::readProgrammingFile(const std::string &fname) { "Program FPGA: Could not close destination file after converting"); } - // unlink(destfname); // delete temporary file - LOG(logDEBUG1) << "Successfully loaded the rawbin file to program memory"; + unlink(destfname); // delete temporary file + LOG(logDEBUG1) << "Read file into memory"; + return buffer; +} + +std::vector DetectorImpl::readKernelFile(const std::string &fname) { + // validate type of file + bool isPof = false; + switch (shm()->detType) { + case JUNGFRAU: + case CHIPTESTBOARD: + case MOENCH: + if (fname.find(".lzma") == std::string::npos) { + throw RuntimeError("Kernel image file must be a lzma file."); + } + isPof = true; + break; + case MYTHEN3: + case GOTTHARD2: + if (fname.find(".bin") == std::string::npos) { + throw RuntimeError("Kernel image file must be an bin file."); + } + break; + default: + throw RuntimeError("Programming kernel image via the package is not implemented for this detector"); + } + + LOG(logINFO) + << "Updating Kernel..."; + LOG(logDEBUG1) << "Programming kernel image with file name:" << fname; + + // check if it exists + struct stat st; + if (stat(fname.c_str(), &st) != 0) { + throw RuntimeError("Program kernel: file does not exist"); + } + + FILE *fp = fopen(fname.c_str(), "rb"); + if (fp == nullptr) { + throw RuntimeError( + "Program kernel: Could not open file: " + + fname); + } + + // get file size to print progress + if (fseek(fp, 0, SEEK_END) != 0) { + throw RuntimeError("Program kernel: Seek error in src file"); + } + size_t filesize = ftell(fp); + if (filesize <= 0) { + throw RuntimeError("Program kernel: Could not get length of file"); + } + rewind(fp); + + std::vector buffer(filesize, 0); + if (fread(buffer.data(), sizeof(char), filesize, fp) != filesize) { + throw RuntimeError("Program kernel: Could not read file"); + } + + if (fclose(fp) != 0) { + throw RuntimeError( + "Program kernel: Could not close file"); + } + LOG(logDEBUG1) << "Read file into memory"; return buffer; } diff --git a/slsDetectorSoftware/src/DetectorImpl.h b/slsDetectorSoftware/src/DetectorImpl.h index 37d57d7bf..c82d7a178 100644 --- a/slsDetectorSoftware/src/DetectorImpl.h +++ b/slsDetectorSoftware/src/DetectorImpl.h @@ -284,13 +284,22 @@ class DetectorImpl : public virtual slsDetectorDefs { /** * Convert raw file - * [Jungfrau][Ctb] from pof file + * [Jungfrau][Ctb][Moench] from pof file * [Mythen3][Gotthard2] from rbf file * @param fname name of pof/rbf file * @returns binary of the program */ std::vector readProgrammingFile(const std::string &fname); + /** + * Read file into memory + * [Jungfrau][Ctb][Moench] from lzma file + * [Mythen3][Gotthard2] from bin file + * @param fname name of file + * @returns binary of the program + */ + std::vector readKernelFile(const std::string &fname); + sls::Result getNumberofUDPInterfaces(Positions pos) const; void setNumberofUDPInterfaces(int n, Positions pos); sls::Result getDefaultDac(defs::dacIndex index, diff --git a/slsDetectorSoftware/src/Module.cpp b/slsDetectorSoftware/src/Module.cpp index dfbc4e001..6156c9065 100644 --- a/slsDetectorSoftware/src/Module.cpp +++ b/slsDetectorSoftware/src/Module.cpp @@ -2492,7 +2492,7 @@ void Module::programFPGA(std::vector buffer) { programFPGAviaNios(buffer); break; default: - throw RuntimeError("Program FPGA is not implemented for this detector"); + throw RuntimeError("Programming FPGA via the package is not implemented for this detector"); } } @@ -2503,7 +2503,8 @@ void Module::copyDetectorServer(const std::string &fname, char args[2][MAX_STR_LENGTH]{}; sls::strcpy_safe(args[0], fname.c_str()); sls::strcpy_safe(args[1], hostname.c_str()); - LOG(logINFO) << "Sending detector server " << args[0] << " from host " + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): Sending detector server " << args[0] << " from host " << args[1]; auto client = DetectorSocket(shm()->hostname, shm()->controlPort); client.Send(F_COPY_DET_SERVER); @@ -2519,9 +2520,26 @@ void Module::copyDetectorServer(const std::string &fname, << "): detector server copied"; } +void Module::updateKernel(std::vector buffer) { + switch (shm()->detType) { + case JUNGFRAU: + case CHIPTESTBOARD: + case MOENCH: + updateKernelviaBlackfin(buffer); + break; + case MYTHEN3: + case GOTTHARD2: + updateKernelviaNios(buffer); + break; + default: + throw RuntimeError("Updating Kernel via the package is not implemented for this detector"); + } +} + void Module::rebootController() { sendToDetector(F_REBOOT_CONTROLLER); - LOG(logINFO) << "Controller rebooted successfully!"; + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): Controller rebooted successfully!"; } uint32_t Module::readRegister(uint32_t addr) const { @@ -2599,11 +2617,25 @@ sls::IpAddr Module::getLastClientIP() const { return sendToDetector(F_GET_LAST_CLIENT_IP); } -std::string Module::execCommand(const std::string &cmd) { +std::string Module::executeCommand(const std::string &cmd) { char arg[MAX_STR_LENGTH]{}; char retval[MAX_STR_LENGTH]{}; sls::strcpy_safe(arg, cmd.c_str()); - sendToDetector(F_EXEC_COMMAND, arg, retval); + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): Sending command " << cmd; + auto client = DetectorSocket(shm()->hostname, shm()->controlPort); + client.Send(F_EXEC_COMMAND); + client.Send(arg); + if (client.Receive() == FAIL) { + std::cout << '\n'; + std::ostringstream os; + os << "Module " << moduleIndex << " (" << shm()->hostname << ")" + << " returned error: " << client.readErrorMessage(); + throw DetectorError(os.str()); + } + client.Receive(retval); + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): command executed"; return retval; } @@ -3409,8 +3441,8 @@ sls_detector_module Module::readSettingsFile(const std::string &fname, void Module::programFPGAviaBlackfin(std::vector buffer) { // send program from memory to detector - LOG(logINFO) << "Sending programming binary (from pof) to module " - << moduleIndex << " (" << shm()->hostname << ")"; + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): Sending programming binary (from pof)"; auto client = DetectorSocket(shm()->hostname, shm()->controlPort); client.Send(F_PROGRAM_FPGA); uint64_t filesize = buffer.size(); @@ -3516,12 +3548,13 @@ void Module::programFPGAviaBlackfin(std::vector buffer) { << " returned error: " << client.readErrorMessage(); throw DetectorError(os.str()); } - LOG(logINFO) << "FPGA programmed successfully"; + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): FPGA programmed successfully"; } void Module::programFPGAviaNios(std::vector buffer) { - LOG(logINFO) << "Sending programming binary (from rbf) to Module " - << moduleIndex << " (" << shm()->hostname << ")"; + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): Sending programming binary (from rbf)"; auto client = DetectorSocket(shm()->hostname, shm()->controlPort); client.Send(F_PROGRAM_FPGA); @@ -3594,6 +3627,112 @@ void Module::programFPGAviaNios(std::vector buffer) { << " returned error: " << client.readErrorMessage(); throw DetectorError(os.str()); } - LOG(logINFO) << "FPGA programmed successfully"; + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): FPGA programmed successfully"; +} + +void Module::updateKernelviaBlackfin(std::vector buffer) { + // send program from memory to detector + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): Sending kernel image (.lzma)"; + auto client = DetectorSocket(shm()->hostname, shm()->controlPort); + client.Send(F_PROGRAM_KERNEL); + uint64_t filesize = buffer.size(); + client.Send(filesize); + + // checksum + std::string checksum = sls::md5_calculate_checksum(buffer.data(), filesize); + LOG(logDEBUG1) << "Checksum:" << checksum; + char cChecksum[MAX_STR_LENGTH]; + memset(cChecksum, 0, MAX_STR_LENGTH); + strcpy(cChecksum, checksum.c_str()); + client.Send(cChecksum); + + // opening file fail + if (client.Receive() == FAIL) { + std::cout << '\n'; + std::ostringstream os; + os << "Module " << moduleIndex << " (" << shm()->hostname << ")" + << " returned error: " << client.readErrorMessage(); + throw DetectorError(os.str()); + } + + // sending program in parts of 2mb each + uint64_t unitprogramsize = 0; + int currentPointer = 0; + while (filesize > 0) { + unitprogramsize = MAX_FPGAPROGRAMSIZE; // 2mb + if (unitprogramsize > filesize) { // less than 2mb + unitprogramsize = filesize; + } + LOG(logDEBUG) << "unitprogramsize:" << unitprogramsize + << "\t filesize:" << filesize; + + client.Send(&buffer[currentPointer], unitprogramsize); + if (client.Receive() == FAIL) { + std::cout << '\n'; + std::ostringstream os; + os << "Module " << moduleIndex << " (" << shm()->hostname << ")" + << " returned error: " << client.readErrorMessage(); + throw DetectorError(os.str()); + } + filesize -= unitprogramsize; + currentPointer += unitprogramsize; + } + + // checksum + if (client.Receive() == FAIL) { + std::ostringstream os; + os << "Module " << moduleIndex << " (" << shm()->hostname << ")" + << " returned error: " << client.readErrorMessage(); + throw DetectorError(os.str()); + } + LOG(logINFO) << "Checksum verified for module " << moduleIndex << " (" + << shm()->hostname << ")"; + + if (client.Receive() == FAIL) { + std::ostringstream os; + os << "Module " << moduleIndex << " (" << shm()->hostname << ")" + << " returned error: " << client.readErrorMessage(); + throw DetectorError(os.str()); + } + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): Kernel udpated successfully"; +} + +void Module::updateKernelviaNios(std::vector buffer) { + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): Sending kernel image (from rbf)"; + + auto client = DetectorSocket(shm()->hostname, shm()->controlPort); + client.Send(F_PROGRAM_FPGA); + uint64_t filesize = buffer.size(); + client.Send(filesize); + + // checksum + std::string checksum = sls::md5_calculate_checksum(buffer.data(), filesize); + LOG(logDEBUG1) << "Checksum:" << checksum; + char cChecksum[MAX_STR_LENGTH]; + memset(cChecksum, 0, MAX_STR_LENGTH); + strcpy(cChecksum, checksum.c_str()); + client.Send(cChecksum); + + // validate file size before sending program + if (client.Receive() == FAIL) { + std::ostringstream os; + os << "Module " << moduleIndex << " (" << shm()->hostname << ")" + << " returned error: " << client.readErrorMessage(); + throw DetectorError(os.str()); + } + client.Send(buffer); + + if (client.Receive() == FAIL) { + std::ostringstream os; + os << "Module " << moduleIndex << " (" << shm()->hostname << ")" + << " returned error: " << client.readErrorMessage(); + throw DetectorError(os.str()); + } + LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname + << "): Kernel updated successfully"; } } // namespace sls diff --git a/slsDetectorSoftware/src/Module.h b/slsDetectorSoftware/src/Module.h index 6bb10a9d3..d81e880fc 100644 --- a/slsDetectorSoftware/src/Module.h +++ b/slsDetectorSoftware/src/Module.h @@ -541,6 +541,7 @@ class Module : public virtual slsDetectorDefs { void resetFPGA(); void copyDetectorServer(const std::string &fname, const std::string &hostname); + void updateKernel(std::vector buffer); void rebootController(); uint32_t readRegister(uint32_t addr) const; uint32_t writeRegister(uint32_t addr, uint32_t val); @@ -565,7 +566,7 @@ class Module : public virtual slsDetectorDefs { bool getLockDetector() const; void setLockDetector(bool lock); sls::IpAddr getLastClientIP() const; - std::string execCommand(const std::string &cmd); + std::string executeCommand(const std::string &cmd); int64_t getNumberOfFramesFromStart() const; int64_t getActualTime() const; int64_t getMeasurementTime() const; @@ -748,6 +749,8 @@ class Module : public virtual slsDetectorDefs { bool trimbits = true); void programFPGAviaBlackfin(std::vector buffer); void programFPGAviaNios(std::vector buffer); + void updateKernelviaBlackfin(std::vector buffer); + void updateKernelviaNios(std::vector buffer); const int moduleIndex; mutable sls::SharedMemory shm{0, 0}; diff --git a/slsDetectorSoftware/tests/test-CmdProxy.cpp b/slsDetectorSoftware/tests/test-CmdProxy.cpp index e6e3851fe..a08db3a4c 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy.cpp @@ -2708,6 +2708,25 @@ TEST_CASE("copydetectorserver", "[.cmd]") { } } +TEST_CASE("updatekernel", "[.cmd]") { + Detector det; + CmdProxy proxy(&det); + auto det_type = det.getDetectorType().squash(); + if (det_type == defs::JUNGFRAU || det_type == defs::CHIPTESTBOARD || + det_type == defs::MOENCH || det_type == defs::MYTHEN3 || + det_type == defs::GOTTHARD2) { + // TODO: send real server? + // std::ostringstream oss; + // proxy.Call("updatekernel",{"juImage_detector.lzma", + // "pc13784"}, -1, PUT, oss); + // REQUIRE(oss.str() == "updatekernel successful\n"); + REQUIRE_THROWS(proxy.Call("updatekernel", {}, -1, GET)); + } else { + REQUIRE_THROWS(proxy.Call("updatekernel", {}, -1, GET)); + REQUIRE_THROWS(proxy.Call("updatekernel", {}, -1, PUT)); + } +} + TEST_CASE("rebootcontroller", "[.cmd]") { Detector det; CmdProxy proxy(&det); diff --git a/slsSupportLib/include/sls/sls_detector_funcs.h b/slsSupportLib/include/sls/sls_detector_funcs.h index 62b232513..d6157f67d 100755 --- a/slsSupportLib/include/sls/sls_detector_funcs.h +++ b/slsSupportLib/include/sls/sls_detector_funcs.h @@ -254,6 +254,7 @@ enum detFuncs { F_GET_READOUT_SPEED, F_SET_READOUT_SPEED, F_GET_KERNEL_VERSION, + F_COPY_KERNEL, NUM_DET_FUNCTIONS, RECEIVER_ENUM_START = 256, /**< detector function should not exceed this @@ -610,6 +611,7 @@ const char* getFunctionNameFromEnum(enum detFuncs func) { case F_GET_READOUT_SPEED: return "F_GET_READOUT_SPEED"; case F_SET_READOUT_SPEED: return "F_SET_READOUT_SPEED"; case F_GET_KERNEL_VERSION: return "F_GET_KERNEL_VERSION"; + case F_COPY_KERNEL: return "F_COPY_KERNEL"; case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS"; case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START";