static signed pibchain2 (void const * memory, char const * filename, flag_t flags) { struct nvm_header2 * nvm_header; size_t origin = ~0; size_t offset = 0; signed module = 0; do { nvm_header = (struct nvm_header2 *)((char *)(memory) + offset); if (LE16TOH (nvm_header->MajorVersion) != 1) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, NVM_HDR_VERSION, filename, module); } return (-1); } if (LE16TOH (nvm_header->MinorVersion) != 1) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, NVM_HDR_VERSION, filename, module); } return (-1); } if (LE32TOH (nvm_header->PrevHeader) != origin) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, NVM_HDR_LINK, filename, module); } return (-1); } if (checksum32 (nvm_header, sizeof (* nvm_header), 0)) { error (0, 0, NVM_HDR_CHECKSUM, filename, module); return (-1); } origin = offset; offset += sizeof (* nvm_header); if (LE32TOH (nvm_header->ImageType) == NVM_IMAGE_PIB) { pibpeek2 ((char *)(memory) + offset); break; } if (checksum32 ((char *)(memory) + offset, LE32TOH (nvm_header->ImageLength), nvm_header->ImageChecksum)) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, NVM_IMG_CHECKSUM, filename, module); } return (-1); } offset += LE32TOH (nvm_header->ImageLength); module++; } while (~nvm_header->NextHeader); return (0); }
signed pibfile2 (struct _file_ const * file) { struct nvm_header2 nvm_header; uint32_t origin = ~0; uint32_t offset = 0; unsigned module = 0; if (lseek (file->file, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, file->name); } do { if (read (file->file, &nvm_header, sizeof (nvm_header)) != sizeof (nvm_header)) { error (1, errno, NVM_HDR_CANTREAD, file->name, module); } if (LE16TOH (nvm_header.MajorVersion) != 1) { error (1, errno, NVM_HDR_VERSION, file->name, module); } if (LE16TOH (nvm_header.MinorVersion) != 1) { error (1, errno, NVM_HDR_VERSION, file->name, module); } if (checksum32 (&nvm_header, sizeof (nvm_header), 0)) { error (1, errno, NVM_HDR_CHECKSUM, file->name, module); } if (LE32TOH (nvm_header.PrevHeader) != origin) { error (1, errno, NVM_HDR_LINK, file->name, module); } if (LE32TOH (nvm_header.ImageType) == NVM_IMAGE_PIB) { if (fdchecksum32 (file->file, LE32TOH (nvm_header.ImageLength), nvm_header.ImageChecksum)) { error (1, errno, NVM_IMG_CHECKSUM, file->name, module); } if (lseek (file->file, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, file->name); } return (0); } if (fdchecksum32 (file->file, LE32TOH (nvm_header.ImageLength), nvm_header.ImageChecksum)) { error (1, errno, NVM_IMG_CHECKSUM, file->name, module); } origin = offset; offset = LE32TOH (nvm_header.NextHeader); module++; } while (~nvm_header.NextHeader); if (lseek (file->file, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, file->name); } return (-1); }
static signed nvmimage2 (void const * memory, size_t extent, char const * filename, flag_t flags) { struct nvm_header1 * nvm_header; unsigned module = 0; uint32_t offset = 0; do { nvm_header = (struct nvm_header1 *)((char *)(memory) + offset); if (LE32TOH (nvm_header->HEADERVERSION) != 0x60000000) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, NVM_HDR_VERSION, filename, module); } return (-1); } if (checksum32 (nvm_header, sizeof (* nvm_header), 0)) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, NVM_HDR_CHECKSUM, filename, module); } return (-1); } offset += sizeof (* nvm_header); extent -= sizeof (* nvm_header); if (_anyset (flags, NVM_VERBOSE)) { printf ("------- %s (%d) -------\n", filename, module); nvmpeek1 (nvm_header); } if (LE32TOH (nvm_header->IMAGETYPE) == NVM_IMAGE_FIRMWARE) { firmware (filename, module, (char *)(memory) + offset, 0x70, flags); } if (checksum32 ((char *)(memory) + offset, LE32TOH (nvm_header->IMAGELENGTH), nvm_header->IMAGECHECKSUM)) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, NVM_IMG_CHECKSUM, filename, module); } return (-1); } offset += LE32TOH (nvm_header->IMAGELENGTH); extent -= LE32TOH (nvm_header->IMAGELENGTH); module++; } while (nvm_header->NEXTHEADER); if (extent) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, NVM_HDR_LINK, filename, module); } } return ((signed)(extent)); }
signed BootParameters2 (struct plc * plc) { unsigned module = 0; struct nvm_header2 nvm_header; if (lseek (plc->PIB.file, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, plc->PIB.name); } do { if (read (plc->PIB.file, &nvm_header, sizeof (nvm_header)) != sizeof (nvm_header)) { error (1, errno, NVM_HDR_CANTREAD, plc->PIB.name, module); } if (LE16TOH (nvm_header.MajorVersion) != 1) { error (1, ECANCELED, NVM_HDR_VERSION, plc->PIB.name, module); } if (LE16TOH (nvm_header.MinorVersion) != 1) { error (1, ECANCELED, NVM_HDR_VERSION, plc->PIB.name, module); } if (checksum32 (&nvm_header, sizeof (nvm_header), 0)) { error (1, ECANCELED, NVM_HDR_CHECKSUM, plc->PIB.name, module); } #if 0 if (_allclr (LE16TOH (nvm_header.ExecuteMask), (1 << (plc->hardwareID - 1)))) { if (lseek (plc->PIB.file, LE32TOH (nvm_header.NextHeader), SEEK_SET) == -1) { error (1, errno, "Can't skip module: %s (%d)", plc->PIB.name, module); } } else #endif if (LE32TOH (nvm_header.ImageType) == NVM_IMAGE_PIB) { if (WriteExecuteParameters2 (plc, module, &nvm_header)) { return (-1); } break; } if (lseek (plc->PIB.file, LE32TOH (nvm_header.NextHeader), SEEK_SET) == -1) { error (1, errno, "Can't skip module: %s (%d)", plc->PIB.name, module); } module++; } while (~nvm_header.NextHeader); return (0); }
static signed function (char const * filename, struct node const * node) { char * memory = 0; signed extent = 0; signed fd; if ((fd = open (filename, O_BINARY | O_RDWR)) == -1) { error (1, errno, FILE_CANTOPEN, filename); } if ((extent = lseek (fd, 0, SEEK_END)) == -1) { error (1, errno, FILE_CANTSIZE, filename); } if (!(memory = (char *)(malloc (extent)))) { error (1, errno, FILE_CANTLOAD, filename); } if (lseek (fd, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, filename); } if (read (fd, memory, extent) != extent) { error (1, errno, FILE_CANTREAD, filename); } if (LE32TOH (* (uint32_t *)(memory)) == 0x60000000) { error (1, 0, FILE_WONTREAD, filename); } if (LE32TOH (* (uint32_t *)(memory)) == 0x00010001) { pibedit2 (filename, node, memory, extent); } else { pibedit1 (node, memory, extent); } if (lseek (fd, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, filename); } if (write (fd, memory, extent) != extent) { error (1, errno, FILE_CANTSAVE, filename); } close (fd); return (0); }
static signed pibedit2 (char const * filename, struct node const * node, char * memory, size_t extent) { struct nvm_header2 * nvm_header; uint32_t origin = ~0; uint32_t offset = 0; unsigned length = 0; unsigned module = 0; do { nvm_header = (struct nvm_header2 *)(memory + offset); if (LE16TOH (nvm_header->MajorVersion) != 1) { error (1, 0, NVM_HDR_VERSION, filename, module); } if (LE16TOH (nvm_header->MinorVersion) != 1) { error (1, 0, NVM_HDR_VERSION, filename, module); } if (LE32TOH (nvm_header->PrevHeader) != origin) { error (1, 0, NVM_HDR_LINK, filename, module); } if (checksum32 (nvm_header, sizeof (* nvm_header), 0)) { error (1, 0, NVM_HDR_CHECKSUM, filename, module); } origin = offset; offset += sizeof (* nvm_header); extent -= sizeof (* nvm_header); length = LE32TOH (nvm_header->ImageLength); if (checksum32 (memory + offset, length, nvm_header->ImageChecksum)) { error (1, 0, NVM_IMG_CHECKSUM, filename, module); } if (LE32TOH (nvm_header->ImageType) == NVM_IMAGE_PIB) { xmledit (node, memory + offset, length); nvm_header->ImageChecksum = checksum32 (memory + offset, length, 0); nvm_header->HeaderChecksum = checksum32 (nvm_header, sizeof (* nvm_header), nvm_header->HeaderChecksum); return (0); } offset += length; extent -= length; module++; } while (~nvm_header->NextHeader); return (-1); }
static void function2 (struct _file_ * file, signed index, flag_t flags) { static signed image = 0; static signed origin = ~0; static signed offset = 0; struct nvm_header2 nvm_header; if (read (file->file, &nvm_header, sizeof (nvm_header)) != sizeof (nvm_header)) { error (1, errno, NVM_HDR_CANTREAD, file->name, image); } if (LE16TOH (nvm_header.MajorVersion) != 1) { error (1, 0, NVM_HDR_VERSION, file->name, image); } if (LE16TOH (nvm_header.MinorVersion) != 1) { error (1, 0, NVM_HDR_VERSION, file->name, image); } if (checksum32 (&nvm_header, sizeof (nvm_header), 0)) { error (1, 0, NVM_HDR_CHECKSUM, file->name, image); } if (~nvm_header.PrevHeader) { error (1, 0, NVM_HDR_LINK, file->name, image); } if (~nvm_header.NextHeader) { error (1, 0, NVM_HDR_LINK, file->name, image); } nvm_header.PrevHeader = HTOLE32 (origin); origin = offset; if (index) { offset += sizeof (nvm_header); offset += LE32TOH (nvm_header.ImageLength); nvm_header.NextHeader = HTOLE32 (offset); } nvm_header.HeaderChecksum = 0; nvm_header.HeaderChecksum = checksum32 (&nvm_header, sizeof (nvm_header), 0); if (write (STDOUT_FILENO, &nvm_header, sizeof (nvm_header)) != sizeof (nvm_header)) { error (1, errno, NVM_HDR_CANTSAVE, file->name, image); } copyimage (file, LE32TOH (nvm_header.ImageLength), image); image++; return; }
signed RemoteHosts (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_sw_ver_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; } * request = (struct vs_sw_ver_request *) (message); struct __packed vs_sw_ver_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint32_t NUMDEVICES; struct __packed { uint8_t MACADDRESS [ETHER_ADDR_LEN]; uint8_t ENUMID; } DEVICE [1]; } * confirm = (struct vs_sw_ver_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif Request (plc, "Request Enumeration ID Table"); memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_EM_ID_TABLE | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } while (ReadMME (plc, 0, (VS_EM_ID_TABLE | MMTYPE_CNF)) > 0) { unsigned count = LE32TOH (confirm->NUMDEVICES); if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); continue; } while (count--) { hexout (confirm->DEVICE [count].MACADDRESS, ETHER_ADDR_LEN, ':', count? ' ': '\n', stdout); } } return (0); }
signed fdmanifest (signed fd, char const * filename, struct nvm_header2 * nvm_header, unsigned module) { off_t extent = LE32TOH (nvm_header->ImageLength); void * memory = malloc (extent); if (!memory) { error (1, 0, FILE_CANTLOAD, filename); } if (read (fd, memory, extent) != (signed)(extent)) { error (1, errno, FILE_CANTREAD, filename); } if (lseek (fd, (off_t)(0) - extent, SEEK_CUR) == -1) { error (1, errno, FILE_CANTSEEK, filename); } printf ("------- %s (%d) -------\n", filename, module); if (manifest (memory, extent)) { error (1, 0, "Bad manifest: %s", filename); } free (memory); return (0); }
void nvmlock2 (struct nvm_header2 * header) { header->ImageChecksum = checksum32 ((char *)(header) + sizeof (* header), LE32TOH (header->ImageLength), 0); header->HeaderChecksum = checksum32 (header, sizeof (* header), header->HeaderChecksum); return; }
void * manifetch (void const * memory, size_t extent, uint32_t type) { uint8_t * offset = (uint8_t *)(memory); while (extent) { struct TLVNode * node = (struct TLVNode *)(offset); if (LE32TOH (node->type) == type) { return ((void *)(&node->data)); } extent -= sizeof (* node) - sizeof (node->size) + LE32TOH (node->size); offset += sizeof (* node) - sizeof (node->size) + LE32TOH (node->size); } return ((void *)(0)); }
bool CPLFirmware::IsValid () const { CPLFirmware::Header const * header; byte const * offset = (byte const *)(this->mbuffer); signed extent = this->mextent; signed image = 0; if ((!this->mbuffer) || (!this->mextent)) { // oerror::error (0, ECANCELED, "No Firmware Image Available"); return (false); } do { std::cout << "start " << image << std::endl; header = (CPLFirmware::Header const *)(offset); #if 1 CPLFirmware::Peek (header); #endif if (LE32TOH (header->HEADERVERSION) != NVM_HEADER_VERSION) { oerror::error (1, 0, "Bad header version"); return (false); } if (omemory::checksum32 (header, sizeof (CPLFirmware::Header), 0)) { oerror::error (1, 0, "Bad header checksum"); return (false); } offset += sizeof (CPLFirmware::Header); extent -= sizeof (CPLFirmware::Header); if (omemory::checksum32 (offset, LE32TOH (header->IMAGELENGTH), header->IMAGECHECKSUM)) { oerror::error (1, 0, "Bad image checksum"); return (false); } offset += header->IMAGELENGTH; extent -= header->IMAGELENGTH; image++; std::cout << "end " << image << std::endl; } while (header->NEXTHEADER); std::cout << "exit" << std::endl; return (!extent); }
static signed chknvm (char const * filename, flag_t flags) { void * memory = (void *)(0); signed extent = 0; signed status = 0; signed fd; if ((fd = open (filename, O_BINARY|O_RDONLY)) == -1) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, FILE_CANTOPEN, filename); } return (-1); } if ((extent = lseek (fd, 0, SEEK_END)) == -1) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, FILE_CANTSIZE, filename); } return (-1); } if (!(memory = malloc (extent))) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, FILE_CANTLOAD, filename); } return (-1); } if (lseek (fd, 0, SEEK_SET)) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, FILE_CANTLOAD, filename); } return (-1); } if (read (fd, memory, extent) != extent) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, FILE_CANTREAD, filename); } return (-1); } close (fd); if (LE32TOH (* (uint32_t *)(memory)) == 0x60000000) { status = nvmimage2 (memory, extent, filename, flags); } else { status = nvmchain2 (memory, extent, filename, flags); } free (memory); return (status); }
signed ClassifierPriorityMap (struct classifier_priority_map * map) { printf ("%s Any ", reword (LE32TOH (map->Priority), actions, SIZEOF (actions))); Classifier (&map->CLASSIFIER); printf (" add perm\n"); return (0); }
void nvmpeek (void const * memory) { if (LE32TOH (*(uint32_t *)(memory)) == 0x60000000) { nvmpeek1 (memory); return; } nvmpeek2 (memory); return; }
static int pio_get(const char* buf, mmap_gpio* pio) { uint32_t port = pio->port - 'A'; if (port > PIO_NR_PORTS) { return -1; } uint32_t val; uint32_t port_num_func, port_num_pull; uint32_t offset_func, offset_pull; port_num_func = pio->pin >> 3; offset_func = ((pio->pin & 0x07) << 2); port_num_pull = pio->pin >> 4; offset_pull = ((pio->pin & 0x0f) << 1); /* func */ val = LE32TOH(PIO_REG_CFG(buf, port, port_num_func)); pio->cfg = (val>>offset_func) & 0x07; /* pull */ val = LE32TOH(PIO_REG_PULL(buf, port, port_num_pull)); pio->pull = (val>>offset_pull) & 0x03; /* dlevel */ val = LE32TOH(PIO_REG_DLEVEL(buf, port, port_num_pull)); pio->drv_level = (val>>offset_pull) & 0x03; /* i/o data */ if (pio->cfg > 1) pio->data = -1; else { val = LE32TOH(PIO_REG_DATA(buf, port)); pio->data = (val >> pio->pin) & 0x01; } return PIO_SUCCESS; }
static void function1 (struct _file_ * file, signed index, flag_t flags) { static signed image = 0; static uint32_t offset = 0; struct nvm_header1 nvm_header; if (read (file->file, &nvm_header, sizeof (nvm_header)) != sizeof (nvm_header)) { error (1, errno, NVM_HDR_CANTREAD, file->name, image); } if (LE32TOH (nvm_header.HEADERVERSION) != 0x60000000) { error (1, 0, NVM_HDR_VERSION, file->name, image); } if (checksum32 (&nvm_header, sizeof (nvm_header), 0)) { error (1, 0, NVM_HDR_CHECKSUM, file->name, image); } if (nvm_header.NEXTHEADER) { error (1, 0, NVM_HDR_LINK, file->name, image); } if (index) { offset += sizeof (nvm_header); offset += LE32TOH (nvm_header.IMAGELENGTH); nvm_header.NEXTHEADER = HTOLE32 (offset); } nvm_header.HEADERCHECKSUM = 0; nvm_header.HEADERCHECKSUM = checksum32 (&nvm_header, sizeof (nvm_header), 0); if (write (STDOUT_FILENO, &nvm_header, sizeof (nvm_header)) != sizeof (nvm_header)) { error (1, errno, NVM_HDR_CANTSAVE, file->name, image); } copyimage (file, LE32TOH (nvm_header.IMAGELENGTH), image); return; }
void nvrampeek (struct config_nvram * config_nvram) { printf ("TYPE=0x%02X ", LE32TOH (config_nvram->NVRAMTYPE)); printf ("(%s) ", NVRAMName (LE32TOH (config_nvram->NVRAMTYPE))); printf ("PAGE=0x%04X ", LE32TOH (config_nvram->NVRAMPAGE)); printf ("BLOCK=0x%04X ", LE32TOH (config_nvram->NVRAMBLOCK)); printf ("SIZE=0x%04X ", LE32TOH (config_nvram->NVRAMSIZE)); printf ("(%d) ", LE32TOH (config_nvram->NVRAMSIZE)); printf ("\n"); return; }
static void function (char const * filename, signed index, flag_t flags) { uint32_t version; struct _file_ file = { -1, filename }; if (_anyset (flags, NVM_VERBOSE)) { error (0, 0, "%s", file.name); } if ((file.file = open (file.name, O_BINARY|O_RDONLY)) == -1) { error (1, errno, FILE_CANTOPEN, file.name); } if (read (file.file, &version, sizeof (version)) != sizeof (version)) { error (1, errno, FILE_CANTREAD, file.name); } if (lseek (file.file, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, file.name); } if (LE32TOH (version) == 0x60000000) { function1 (&file, index, flags); } else { function2 (&file, index, flags); } close (file.file); return; }
static void function (char const * filename, flag_t flags) { uint32_t version; signed ifd; if ((ifd = open (filename, O_BINARY|O_RDONLY)) == -1) { error (1, errno, FILE_CANTOPEN, filename); } if (read (ifd, &version, sizeof (version)) != sizeof (version)) { error (1, errno, FILE_CANTREAD, filename); } close (ifd); if (LE32TOH (version) == 0x60000000) { function1 (filename, flags); } else { function2 (filename, flags); } return; }
void nvmpeek1 (void const * memory) { extern char const * nvm_imagetypes []; extern char const * nvm_platforms []; struct nvm_header1 * nvm_header = (struct nvm_header1 *)(memory); char const * string = "Unknown"; char platform [100]; printf ("\tHeader Version = 0x%08X-%02X\n", LE32TOH (nvm_header->HEADERVERSION), nvm_header->HEADERMINORVERSION); printf ("\tHeader Checksum = 0x%08X\n", LE32TOH (nvm_header->HEADERCHECKSUM)); printf ("\tHeader Next = 0x%08X\n", LE32TOH (nvm_header->NEXTHEADER)); printf ("\tFlash Address = 0x%08X\n", LE32TOH (nvm_header->IMAGEROMADDR)); printf ("\tImage Address = 0x%08X\n", LE32TOH (nvm_header->IMAGEADDRESS)); printf ("\tEntry Address = 0x%08X\n", LE32TOH (nvm_header->ENTRYPOINT)); printf ("\tImage Checksum = 0x%08X\n", LE32TOH (nvm_header->IMAGECHECKSUM)); printf ("\tImage Size = 0x%08X (%d)\n", LE32TOH (nvm_header->IMAGELENGTH), LE32TOH (nvm_header->IMAGELENGTH)); if (LE32TOH (nvm_header->IMAGETYPE) < NVM_IMAGETYPES) { string = nvm_imagetypes [LE32TOH (nvm_header->IMAGETYPE)]; } printf ("\tImage Type = %s\n", string); strfbits (platform, sizeof (platform), nvm_platforms, "|", LE16TOH (nvm_header->IGNOREMASK)); printf ("\tImage Omit = %s\n", platform); return; }
signed WriteMOD (struct plc * plc, uint8_t module, void const * memory, size_t extent) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_wr_mod_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MODULEID; uint8_t MACCESS; uint16_t MLENGTH; uint32_t MOFFSET; uint32_t MCHKSUM; uint8_t MBUFFER [PLC_RECORD_SIZE]; } * request = (struct vs_wr_mod_request *) (message); struct __packed vs_wr_mod_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint8_t MODULEID; uint8_t MACCESS; uint16_t MLENGTH; uint32_t MOFFSET; } * confirm = (struct vs_wr_mod_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif uint32_t length = PLC_RECORD_SIZE; uint32_t offset = 0; while (extent) { memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_WR_MOD | MMTYPE_REQ)); if (length > extent) { length = (signed)(extent); } memcpy (request->MBUFFER, (byte *)(memory) + offset, length); request->MODULEID = module; request->MACCESS = 0; request->MLENGTH = HTOLE16 (length); request->MOFFSET = HTOLE32 (offset); request->MCHKSUM = checksum32 (request->MBUFFER, length, 0); plc->packetsize = sizeof (* request); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_WR_MOD | MMTYPE_CNF)) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } if (LE16TOH (confirm->MLENGTH) != length) { error (PLC_EXIT (plc), 0, PLC_ERR_LENGTH); return (-1); } if (LE32TOH (confirm->MOFFSET) != offset) { error (PLC_EXIT (plc), 0, PLC_ERR_OFFSET); return (-1); } offset += length; extent -= length; } return (0); }
signed WriteExecuteFirmware (struct plc * plc, unsigned module, void const * nvm_header) { return ((LE32TOH (*(uint32_t *)(nvm_header)) == 0x60000000)? WriteExecuteFirmware1 (plc, module, nvm_header): WriteExecuteFirmware2 (plc, module, nvm_header)); }
signed ModuleWrite (struct plc * plc, struct _file_ * file, unsigned index, struct vs_module_spec * vs_module_spec) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_module_operation_write_request { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint32_t RESERVED; uint8_t NUM_OP_DATA; struct __packed { uint16_t MOD_OP; uint16_t MOD_OP_DATA_LEN; uint32_t MOD_OP_RSVD; uint32_t MOD_OP_SESSION_ID; uint8_t MODULE_IDX; uint16_t MODULE_ID; uint16_t MODULE_SUB_ID; uint16_t MODULE_LENGTH; uint32_t MODULE_OFFSET; } MODULE_SPEC; uint8_t MODULE_DATA [PLC_MODULE_SIZE]; } * request = (struct vs_module_operation_write_request *)(message); struct __packed vs_module_operation_write_confirm { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint16_t MSTATUS; uint16_t ERR_REC_CODE; uint32_t RESERVED; uint8_t NUM_OP_DATA; struct __packed { uint16_t MOD_OP; uint16_t MOD_OP_DATA_LEN; uint32_t MOD_OP_RSVD; uint32_t MOD_OP_SESSION_ID; uint8_t MODULE_IDX; uint16_t MODULE_ID; uint16_t MODULE_SUB_ID; uint16_t MODULE_LENGTH; uint32_t MODULE_OFFSET; } MODULE_SPEC; } * confirm = (struct vs_module_operation_write_confirm *)(message); #ifndef __GNUC__ #pragma pack (pop) #endif unsigned timeout = channel->timeout; uint16_t length = PLC_MODULE_SIZE; uint32_t extent = vs_module_spec->MODULE_LENGTH; uint32_t offset = 0; Request (plc, "Flash %s", file->name); while (extent) { memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, HOMEPLUG_MTYPE); QualcommHeader (&request->qualcomm, 0, (VS_MODULE_OPERATION | MMTYPE_REQ)); plc->packetsize = sizeof (struct vs_module_operation_write_request); if (length > extent) { length = extent; } if (read (file->file, request->MODULE_DATA, length) != length) { error (1, errno, FILE_CANTREAD, file->name); } request->NUM_OP_DATA = 1; request->MODULE_SPEC.MOD_OP = HTOLE16 (PLC_MOD_OP_WRITE_MODULE); request->MODULE_SPEC.MOD_OP_DATA_LEN = HTOLE16 (sizeof (request->MODULE_SPEC) + sizeof (request->MODULE_DATA)); request->MODULE_SPEC.MOD_OP_SESSION_ID = HTOLE32 (plc->cookie); request->MODULE_SPEC.MODULE_IDX = index; request->MODULE_SPEC.MODULE_ID = HTOLE16 (vs_module_spec->MODULE_ID); request->MODULE_SPEC.MODULE_SUB_ID = HTOLE16 (vs_module_spec->MODULE_SUB_ID); request->MODULE_SPEC.MODULE_LENGTH = HTOLE16 (length); request->MODULE_SPEC.MODULE_OFFSET = HTOLE32 (offset); #if 0 fprintf (stderr, "RESERVED 0x%08X\n", LE32TOH (request->RESERVED)); fprintf (stderr, "NUM_OP_DATA %d\n", request->NUM_OP_DATA); fprintf (stderr, "MOD_OP 0x%02X\n", LE16TOH (request->MODULE_SPEC.MOD_OP)); fprintf (stderr, "MOD_OP_DATA_LEN %d\n", LE16TOH (request->MODULE_SPEC.MOD_OP_DATA_LEN)); fprintf (stderr, "RESERVED 0x%08X\n", LE32TOH (request->MODULE_SPEC.MOD_OP_RSVD)); fprintf (stderr, "MODULE_ID 0x%04X\n", LE16TOH (request->MODULE_SPEC.MODULE_ID)); fprintf (stderr, "MODULE_SUB_ID 0x%04X\n", LE16TOH (request->MODULE_SPEC.MODULE_SUB_ID)); fprintf (stderr, "MODULE_LENGTH %d\n", LE16TOH (request->MODULE_SPEC.MODULE_LENGTH)); fprintf (stderr, "MODULE_OFFSET 0x%08X\n", LE32TOH (request->MODULE_SPEC.MODULE_OFFSET)); #endif if (SendMME (plc) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTSEND); return (-1); } channel->timeout = PLC_MODULE_WRITE_TIMEOUT; if (ReadMME (plc, 0, (VS_MODULE_OPERATION | MMTYPE_CNF)) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTREAD); channel->timeout = timeout; return (-1); } channel->timeout = timeout; #if 0 fprintf (stderr, "MSTATUS 0x%04X\n", LE16TOH (confirm->MSTATUS)); fprintf (stderr, "ERROR_REC_CODE %d\n", LE16TOH (confirm->ERR_REC_CODE)); fprintf (stderr, "RESERVED 0x%08X\n", LE32TOH (confirm->RESERVED)); fprintf (stderr, "NUM_OP_DATA %d\n", confirm->NUM_OP_DATA); fprintf (stderr, "MOD_OP 0x%02X\n", LE16TOH (request->MODULE_SPEC.MOD_OP)); fprintf (stderr, "MOD_OP_DATA_LEN %d\n", LE16TOH (confirm->MODULE_SPEC.MOD_OP_DATA_LEN)); fprintf (stderr, "RESERVED 0x%08X\n", LE32TOH (confirm->MODULE_SPEC.MOD_OP_RSVD)); fprintf (stderr, "MODULE_ID 0x%04X\n", LE16TOH (confirm->MODULE_SPEC.MODULE_ID)); fprintf (stderr, "MODULE_SUB_ID 0x%04X\n", LE16TOH (confirm->MODULE_SPEC.MODULE_SUB_ID)); fprintf (stderr, "MODULE_LENGTH %d\n", LE16TOH (confirm->MODULE_SPEC.MODULE_LENGTH)); fprintf (stderr, "MODULE_OFFSET 0x%08X\n", LE32TOH (request->MODULE_SPEC.MODULE_OFFSET)); #endif if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } if (LE16TOH (confirm->MODULE_SPEC.MODULE_LENGTH) != length) { error ((plc->flags & PLC_BAILOUT), 0, PLC_ERR_LENGTH); return (-1); } if (LE32TOH (confirm->MODULE_SPEC.MODULE_OFFSET) != offset) { error ((plc->flags & PLC_BAILOUT), 0, PLC_ERR_OFFSET); return (-1); } extent -= length; offset += length; } return (0); }
signed WriteExecuteFirmware1 (struct plc * plc, unsigned module, const struct nvm_header1 * nvm_header) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_write_execute_request { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint32_t CLIENT_SESSION_ID; uint32_t SERVER_SESSION_ID; uint32_t FLAGS; uint8_t ALLOWED_MEM_TYPES [8]; uint32_t TOTAL_LENGTH; uint32_t CURR_PART_LENGTH; uint32_t CURR_PART_OFFSET; uint32_t START_ADDR; uint32_t CHECKSUM; uint8_t RESERVED2 [8]; uint8_t IMAGE [PLC_MODULE_SIZE]; } * request = (struct vs_write_execute_request *) (message); struct __packed vs_write_execute_confirm { struct ethernet_std ethernet; struct qualcomm_std qualcomm; uint32_t MSTATUS; uint32_t CLIENT_SESSION_ID; uint32_t SERVER_SESSION_ID; uint32_t FLAGS; uint8_t ALLOWED_MEM_TYPES [8]; uint32_t TOTAL_LENGTH; uint32_t CURR_PART_LENGTH; uint32_t CURR_PART_OFFSET; uint32_t START_ADDR; uint32_t CHECKSUM; uint8_t RESERVED2 [8]; uint32_t CURR_PART_ABSOLUTE_ADDR; uint32_t ABSOLUTE_START_ADDR; } * confirm = (struct vs_write_execute_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif unsigned action = PLC_MODULE_ABSOLUTE; uint32_t length = PLC_MODULE_SIZE; uint32_t offset = LE32TOH (nvm_header->IMAGEADDRESS); uint32_t extent = LE32TOH (nvm_header->IMAGELENGTH); Request (plc, "Write %s (%d) (%08X:%d)", plc->NVM.name, module, offset, extent); while (extent) { memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_WRITE_AND_EXECUTE_APPLET | MMTYPE_REQ)); if (length > extent) { Request (plc, "Start %s (%d) (%08X)", plc->NVM.name, module, LE32TOH (nvm_header->ENTRYPOINT)); length = extent; action |= PLC_MODULE_EXECUTE; } if (read (plc->NVM.file, request->IMAGE, length) != (signed)(length)) { error (1, errno, FILE_CANTREAD, plc->NVM.name); } request->CLIENT_SESSION_ID = HTOLE32 (plc->cookie); request->SERVER_SESSION_ID = HTOLE32 (0); request->FLAGS = HTOLE32 (action); request->ALLOWED_MEM_TYPES [0] = 1; request->TOTAL_LENGTH = nvm_header->IMAGELENGTH; request->CURR_PART_LENGTH = HTOLE32 (length); request->CURR_PART_OFFSET = HTOLE32 (offset); request->START_ADDR = nvm_header->ENTRYPOINT; request->CHECKSUM = nvm_header->IMAGECHECKSUM; plc->packetsize = sizeof (* request); if (SendMME (plc) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_WRITE_AND_EXECUTE_APPLET | MMTYPE_CNF)) <= 0) { error ((plc->flags & PLC_BAILOUT), errno, CHANNEL_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } if (LE32TOH (confirm->CURR_PART_LENGTH) != length) { error ((plc->flags & PLC_BAILOUT), 0, PLC_ERR_LENGTH); return (-1); } if (LE32TOH (confirm->CURR_PART_OFFSET) != offset) { error ((plc->flags & PLC_BAILOUT), 0, PLC_ERR_OFFSET); return (-1); } offset += length; extent -= length; } return (0); }
signed EmulateHost (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); static char const * actions [] = { "start device", "store firmware", "store parameters", "update host", "config memory", "restore defaults", "unknown" }; #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_host_action_ind { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MACTION; uint8_t MAJOR_VERSION; uint8_t MINOR_VERSION; } * indicate = (struct vs_host_action_ind *) (message); #if 0 struct __packed vs_host_action_rsp { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; } * response = (struct vs_host_action_rsp *) (message); #endif #ifndef __GNUC__ #pragma pack (pop) #endif struct nvm_header1 nvm_header; struct pib_header pib_header; uint32_t offset; char const * PIB = plc->PIB.name; char const * NVM = plc->NVM.name; signed timer = channel->timeout; signed status = 0; Request (plc, "Waiting for Host Action"); while (1) { channel->timeout = plc->timer; status = ReadMME (plc, 0, (VS_HOST_ACTION | MMTYPE_IND)); channel->timeout = timer; if (status < 0) { break; } if (status > 0) { printf ("\n"); if (indicate->MACTION < (sizeof (actions) / sizeof (char const *))) { Confirm (plc, "Host Action Request is (%d) %s.", indicate->MACTION, actions [indicate->MACTION]); } else { error (0, ENOTSUP, "Host Action 0x%0X", indicate->MACTION); continue; } memcpy (channel->peer, indicate->ethernet.OSA, sizeof (channel->peer)); channel->timeout = timer; if (indicate->MACTION == 0x00) { unsigned module = 0; char firmware [PLC_VERSION_STRING]; if (HostActionResponse (plc)) { return (-1); } if (lseek (plc->PIB.file, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, plc->PIB.name); } if (read (plc->PIB.file, &pib_header, sizeof (pib_header)) != sizeof (pib_header)) { error (1, errno, FILE_CANTREAD, plc->PIB.name); } if (lseek (plc->PIB.file, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, plc->PIB.name); } if (BE16TOH (*(uint16_t *)(&pib_header)) < 0x0305) { offset = LEGACY_PIBOFFSET; } else if (BE16TOH (*(uint16_t *)(&pib_header)) < 0x0500) { offset = INT6x00_PIBOFFSET; } else { offset = AR7x00_PIBOFFSET; } if (WriteMEM (plc, &plc->PIB, 0, offset, LE16TOH (pib_header.PIBLENGTH))) { return (-1); } if (lseek (plc->NVM.file, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, plc->NVM.name); } if (read (plc->NVM.file, &nvm_header, sizeof (nvm_header)) != sizeof (nvm_header)) { error (1, errno, FILE_CANTREAD, plc->NVM.name); } while (nvm_header.NEXTHEADER) { lseek (plc->NVM.file, LE32TOH (nvm_header.NEXTHEADER), SEEK_SET); if (read (plc->NVM.file, &nvm_header, sizeof (nvm_header)) != sizeof (nvm_header)) { error (1, errno, FILE_CANTREAD, plc->NVM.name); } module++; } if (WriteFirmware1 (plc, module, &nvm_header)) { return (-1); } if (StartFirmware1 (plc, module, &nvm_header)) { return (-1); } if (WaitForStart (plc, firmware, sizeof (firmware))) { return (-1); } if (_anyset (plc->flags, PLC_FLASH_DEVICE)) { if (WriteNVM (plc)) { return (-1); } if (WritePIB (plc)) { return (-1); } if (FlashNVM (plc)) { return (-1); } } continue; } if (indicate->MACTION == 0x01) { if (HostActionResponse (plc)) { return (-1); } close (plc->NVM.file); if (ReadFirmware1 (plc)) { return (-1); } if ((plc->NVM.file = open (plc->NVM.name = plc->nvm.name, O_BINARY|O_RDONLY)) == -1) { error (1, errno, "%s", plc->NVM.name); } if (ResetDevice (plc)) { return (-1); } continue; } if (indicate->MACTION == 0x02) { if (HostActionResponse (plc)) { return (-1); } close (plc->PIB.file); if (ReadParameters1 (plc)) { return (-1); } if ((plc->PIB.file = open (plc->PIB.name = plc->pib.name, O_BINARY|O_RDONLY)) == -1) { error (1, errno, "%s", plc->PIB.name); } if (ResetDevice (plc)) { return (-1); } continue; } if (indicate->MACTION == 0x03) { if (HostActionResponse (plc)) { return (-1); } close (plc->NVM.file); if (ReadFirmware1 (plc)) { return (-1); } if ((plc->NVM.file = open (plc->NVM.name = plc->nvm.name, O_BINARY|O_RDONLY)) == -1) { error (1, errno, "%s", plc->NVM.name); } close (plc->PIB.file); if (ReadParameters1 (plc)) { return (-1); } if ((plc->PIB.file = open (plc->PIB.name = plc->pib.name, O_BINARY|O_RDONLY)) == -1) { error (1, errno, "%s", plc->PIB.name); } if (ResetDevice (plc)) { return (-1); } continue; } if (indicate->MACTION == 0x04) { #if 0 /* * Due to an omission in the INT6300 BootLoader, responding to this VS_HOST_ACTION * indication will suppress subsequent VS_HOST_ACTION messages and the device will * not request firmware and parameters; this may be corrected on the INT6400; */ if (HostActionResponse (plc)) { return (-1); } #endif if (WriteCFG (plc)) { return (-1); } /* * At this point, one could download firmware and parameters without waiting for * further requests from the device; however, we elect to wait for them since it * is 'good form'; a device should send code 0x00 within 10 seconds of this one; */ continue; } if (indicate->MACTION == 0x05) { if (HostActionResponse (plc)) { return (-1); } close (plc->NVM.file); if ((plc->NVM.file = open (plc->NVM.name = NVM, O_BINARY|O_RDONLY)) == -1) { error (1, errno, "%s", plc->NVM.name); } close (plc->PIB.file); if ((plc->PIB.file = open (plc->PIB.name = PIB, O_BINARY|O_RDONLY)) == -1) { error (1, errno, "%s", plc->PIB.name); } if (ResetDevice (plc)) { return (-1); } continue; } error (0, ENOSYS, "Host Action 0x%0X", indicate->MACTION); } } return (0); }
signed WriteFirmware1 (struct plc * plc, unsigned module, const struct nvm_header1 * nvm_header) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_wr_mem_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint32_t MOFFSET; uint32_t MLENGTH; uint8_t BUFFER [PLC_RECORD_SIZE]; } * request = (struct vs_wr_mem_request *) (message); struct __packed vs_wr_mem_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint32_t MOFFSET; uint32_t MLENGTH; } * confirm = (struct vs_wr_mem_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif uint32_t length = PLC_RECORD_SIZE; uint32_t offset = LE32TOH (nvm_header->IMAGEADDRESS); uint32_t extent = LE32TOH (nvm_header->IMAGELENGTH); Request (plc, "Write %s (%d) (%08X:%d)", plc->NVM.name, module, offset, extent); while (extent) { memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_WR_MEM | MMTYPE_REQ)); if (length > extent) { length = extent; } if (read (plc->NVM.file, request->BUFFER, length) != (signed)(length)) { error (1, errno, FILE_CANTREAD, plc->NVM.name); } request->MLENGTH = HTOLE32 (length); request->MOFFSET = HTOLE32 (offset); plc->packetsize = sizeof (* request); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_WR_MEM | MMTYPE_CNF)) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } if (LE32TOH (confirm->MLENGTH) != length) { error (PLC_EXIT (plc), 0, PLC_ERR_LENGTH); return (-1); } if (LE32TOH (confirm->MOFFSET) != offset) { error (PLC_EXIT (plc), 0, PLC_ERR_OFFSET); return (-1); } offset += length; extent -= length; } return (0); }
signed WriteParameters (struct plc * plc, unsigned module, void const * nvm_header) { return ((LE32TOH (*(uint32_t *)(nvm_header)) == 0x60000000)? WriteParameters1 (plc, module, nvm_header): WriteParameters2 (plc, module, nvm_header)); }
signed ReadFirmware1 (struct plc * plc) { struct channel * channel = (struct channel *)(plc->channel); struct message * message = (struct message *)(plc->message); #ifndef __GNUC__ #pragma pack (push,1) #endif struct __packed vs_rd_mod_request { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MODULEID; uint8_t MACCESS; uint16_t MLENGTH; uint32_t MOFFSET; uint8_t MSECRET [16]; } * request = (struct vs_rd_mod_request *) (message); struct __packed vs_rd_mod_confirm { struct ethernet_hdr ethernet; struct qualcomm_hdr qualcomm; uint8_t MSTATUS; uint8_t RES [3]; uint8_t MODULEID; uint8_t RESERVED; uint16_t MLENGTH; uint32_t MOFFSET; uint32_t CHKSUM; uint8_t BUFFER [PLC_RECORD_SIZE]; } * confirm = (struct vs_rd_mod_confirm *) (message); #ifndef __GNUC__ #pragma pack (pop) #endif uint32_t header = 0; uint32_t extent = 0; uint32_t offset = 0; uint16_t length = PLC_RECORD_SIZE; Request (plc, "Read Firmware from Device"); if (lseek (plc->nvm.file, 0, SEEK_SET)) { error (PLC_EXIT (plc), errno, FILE_CANTHOME, plc->nvm.name); return (1); } do { memset (message, 0, sizeof (* message)); EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type); QualcommHeader (&request->qualcomm, 0, (VS_RD_MOD | MMTYPE_REQ)); plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN); request->MODULEID = VS_MODULE_MAC; request->MLENGTH = HTOLE16 (length); request->MOFFSET = HTOLE32 (offset); if (SendMME (plc) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND); return (-1); } if (ReadMME (plc, 0, (VS_RD_MOD | MMTYPE_CNF)) <= 0) { error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD); return (-1); } if (confirm->MSTATUS) { Failure (plc, PLC_WONTDOIT); return (-1); } if (LE16TOH (confirm->MLENGTH) != length) { error (PLC_EXIT (plc), 0, PLC_ERR_LENGTH); return (-1); } if (LE32TOH (confirm->MOFFSET) != offset) { error (PLC_EXIT (plc), 0, PLC_ERR_OFFSET); return (-1); } length = LE16TOH (confirm->MLENGTH); offset = LE32TOH (confirm->MOFFSET); if (checksum32 (confirm->BUFFER, length, confirm->CHKSUM)) { error (PLC_EXIT (plc), ECANCELED, "Bad Packet Checksum"); return (-1); } if (offset == extent) { struct nvm_header1 * nvm_header = (struct nvm_header1 *)(confirm->BUFFER); if (checksum32 (nvm_header, sizeof (* nvm_header), 0)) { error (PLC_EXIT (plc), ECANCELED, "Bad Header Checksum"); return (-1); } if (LE32TOH (nvm_header->HEADERVERSION) != 0x60000000) { error (PLC_EXIT (plc), ECANCELED, "Bad Header Version"); return (-1); } extent += sizeof (* nvm_header); extent += LE32TOH (nvm_header->IMAGELENGTH); header = LE32TOH (nvm_header->NEXTHEADER); } if ((offset + length) > extent) { length = extent - offset; } if (lseek (plc->nvm.file, offset, SEEK_SET) != (off_t)(offset)) { error (PLC_EXIT (plc), errno, FILE_CANTSEEK, plc->nvm.name); return (-1); } if (write (plc->nvm.file, confirm->BUFFER, length) != (signed)(length)) { error (PLC_EXIT (plc), errno, FILE_CANTSEEK, plc->nvm.name); return (-1); } offset += length; length = 1024; } while ((header) || (offset < extent)); Confirm (plc, "Read %s", plc->nvm.name); return (0); }
static signed nvmchain2 (void const * memory, size_t extent, char const * filename, flag_t flags) { struct nvm_header2 * nvm_header; unsigned module = 0; uint32_t origin = ~0; uint32_t offset = 0; uint32_t length = 0; do { nvm_header = (struct nvm_header2 *)((char *)(memory) + offset); if (LE16TOH (nvm_header->MajorVersion) != 1) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, NVM_HDR_VERSION, filename, module); } return (-1); } if (LE16TOH (nvm_header->MinorVersion) != 1) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, NVM_HDR_VERSION, filename, module); } return (-1); } if (LE32TOH (nvm_header->PrevHeader) != origin) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, NVM_HDR_LINK, filename, module); } return (-1); } if (checksum32 (nvm_header, sizeof (* nvm_header), 0)) { if (_allclr (flags, NVM_SILENCE)) { error (0, 0, NVM_HDR_CHECKSUM, filename, module); } return (-1); } origin = offset; offset += sizeof (* nvm_header); extent -= sizeof (* nvm_header); length = LE32TOH (nvm_header->ImageLength); if (_anyset (flags, NVM_VERBOSE)) { printf ("------- %s (%d) -------\n", filename, module); nvmpeek2 (nvm_header); } if (LE32TOH (nvm_header->ImageType) == NVM_IMAGE_MANIFEST) { if (_anyset (flags, NVM_MANIFEST)) { printf ("------- %s (%d) -------\n", filename, module); manifest ((char *)(memory) + offset, length); return (0); } } if (checksum32 ((char *)(memory) + offset, length, nvm_header->ImageChecksum)) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, NVM_IMG_CHECKSUM, filename, module); } return (-1); } offset += length; extent -= length; module++; } while (~nvm_header->NextHeader); if (extent) { if (_allclr (flags, NVM_SILENCE)) { error (0, errno, NVM_HDR_LINK, filename, module); } } return (0); }