int flash_register(struct blocklevel_device *bl) { uint64_t size; uint32_t block_size; struct ffs_handle *ffs; struct dt_node *node; struct flash *flash; const char *name; int rc; rc = blocklevel_get_info(bl, &name, &size, &block_size); if (rc) return rc; if (!name) name = "(unnamed)"; prlog(PR_INFO, "FLASH: registering flash device %s " "(size 0x%llx, blocksize 0x%x)\n", name, size, block_size); flash = malloc(sizeof(struct flash)); if (!flash) { prlog(PR_ERR, "FLASH: Error allocating flash structure\n"); return OPAL_RESOURCE; } flash->busy = false; flash->bl = bl; flash->no_erase = !(bl->flags & WRITE_NEED_ERASE); flash->size = size; flash->block_size = block_size; flash->id = num_flashes(); rc = ffs_init(0, flash->size, bl, &ffs, 1); if (rc) { /** * @fwts-label NoFFS * @fwts-advice System flash isn't formatted as expected. * This could mean several OPAL utilities do not function * as expected. e.g. gard, pflash. */ prlog(PR_WARNING, "FLASH: No ffs info; " "using raw device only\n"); ffs = NULL; } node = flash_add_dt_node(flash, flash->id); setup_system_flash(flash, node, name, ffs); if (ffs) ffs_close(ffs); lock(&flash_lock); list_add(&flashes, &flash->list); unlock(&flash_lock); return OPAL_SUCCESS; }
static void lookup_partition(const char *name) { int rc; if (flash_side == 1) { uint32_t other_side_offset; rc = open_partition("OTHER_SIDE"); if (rc == FFS_ERR_PART_NOT_FOUND) fprintf(stderr, "side 1 was specified but there doesn't appear" " to be a second side to this flash\n"); if (rc) exit(1); /* Just need to know where it starts */ rc = ffs_part_info(ffsh, ffs_index, NULL, &other_side_offset, NULL, NULL, NULL); if (rc) exit(1); ffs_close(ffsh); ffsh = NULL; ffs_toc = other_side_offset; } rc = open_partition(name); if (rc) exit(1); }
static void flash_access_cleanup_bmc(void) { if(ffsh) ffs_close(ffsh); flash_exit(fl_chip); ast_sf_close(fl_ctrl); close_devs(); }
static void print_ffs_info(uint32_t toc_offset) { struct ffs_handle *ffs_handle; uint32_t other_side_offset = 0; int rc; uint32_t i; rc = ffs_init(toc_offset, fl_total_size, bl, &ffs_handle, 0); if (rc) { fprintf(stderr, "Error %d opening ffs !\n", rc); return; } printf("\n"); printf("TOC@0x%08x Partitions:\n", toc_offset); printf("-----------\n"); for (i = 0;; i++) { uint32_t start, size, act, end; bool ecc; char *name; rc = ffs_part_info(ffs_handle, i, &name, &start, &size, &act, &ecc); if (rc == FFS_ERR_PART_NOT_FOUND) break; if (rc) { fprintf(stderr, "Error %d scanning partitions\n", rc); break; } end = start + size; printf("ID=%02d %15s %08x..%08x (actual=%08x) %s\n", i, name, start, end, act, ecc ? "[ECC]" : ""); if (strcmp(name, "OTHER_SIDE") == 0) other_side_offset = start; free(name); } ffs_close(ffs_handle); if (other_side_offset) print_ffs_info(other_side_offset); }
static void flash_access_cleanup_pnor(void) { /* Re-lock flash */ if(need_relock) set_wrprotect(true); if(ffsh) ffs_close(ffsh); flash_exit(fl_chip); #ifdef __powerpc__ if(using_sfc) sfc_close(fl_ctrl); else ast_sf_close(fl_ctrl); #else ast_sf_close(fl_ctrl); #endif close_devs(); }
/* * load a resource from FLASH * buf and len shouldn't account for ECC even if partition is ECCed. * * The API here is a bit strange. * If resource has a STB container, buf will contain it * If loading subpartition with STB container, buff will *NOT* contain it * For trusted boot, the whole partition containing the subpart is measured. * * Additionally, the logic to work out how much to read from flash is insane. */ static int flash_load_resource(enum resource_id id, uint32_t subid, void *buf, size_t *len) { int i; int rc = OPAL_RESOURCE; struct ffs_handle *ffs; struct flash *flash; const char *name; bool status = false; bool ecc; bool part_signed = false; void *bufp = buf; size_t bufsz = *len; int ffs_part_num, ffs_part_start, ffs_part_size; int content_size = 0; int offset = 0; lock(&flash_lock); if (!system_flash) { /** * @fwts-label SystemFlashNotFound * @fwts-advice No system flash was found. Check for missing * calls flash_register(...). */ prlog(PR_WARNING, "FLASH: Can't load resource id:%i. " "No system flash found\n", id); goto out_unlock; } flash = system_flash; if (flash->busy) goto out_unlock; for (i = 0, name = NULL; i < ARRAY_SIZE(part_name_map); i++) { if (part_name_map[i].id == id) { name = part_name_map[i].name; break; } } if (!name) { prerror("FLASH: Couldn't find partition for id %d\n", id); goto out_unlock; } /* * If partition doesn't have a subindex but the caller specifies one, * we fail. eg. kernel partition doesn't have a subindex */ if ((part_name_map[i].subid == RESOURCE_SUBID_NONE) && (subid != RESOURCE_SUBID_NONE)) { prerror("PLAT: Partition %s doesn't have subindex\n", name); goto out_unlock; } rc = ffs_init(0, flash->size, flash->bl, &ffs, 1); if (rc) { prerror("FLASH: Can't open ffs handle: %d\n", rc); goto out_unlock; } rc = ffs_lookup_part(ffs, name, &ffs_part_num); if (rc) { /* This is not an error per-se, some partitions * are purposefully absent, don't spam the logs */ prlog(PR_DEBUG, "FLASH: No %s partition\n", name); goto out_free_ffs; } rc = ffs_part_info(ffs, ffs_part_num, NULL, &ffs_part_start, NULL, &ffs_part_size, &ecc); if (rc) { prerror("FLASH: Failed to get %s partition info\n", name); goto out_free_ffs; } prlog(PR_DEBUG,"FLASH: %s partition %s ECC\n", name, ecc ? "has" : "doesn't have"); if (ffs_part_size < SECURE_BOOT_HEADERS_SIZE) { prerror("FLASH: secboot headers bigger than " "partition size 0x%x\n", ffs_part_size); goto out_free_ffs; } rc = blocklevel_read(flash->bl, ffs_part_start, bufp, SECURE_BOOT_HEADERS_SIZE); if (rc) { prerror("FLASH: failed to read the first 0x%x from " "%s partition, rc %d\n", SECURE_BOOT_HEADERS_SIZE, name, rc); goto out_free_ffs; } part_signed = stb_is_container(bufp, SECURE_BOOT_HEADERS_SIZE); prlog(PR_DEBUG, "FLASH: %s partition %s signed\n", name, part_signed ? "is" : "isn't"); /* * part_start/size are raw pointers into the partition. * ie. they will account for ECC if included. */ if (part_signed) { bufp += SECURE_BOOT_HEADERS_SIZE; bufsz -= SECURE_BOOT_HEADERS_SIZE; content_size = stb_sw_payload_size(buf, SECURE_BOOT_HEADERS_SIZE); *len = content_size + SECURE_BOOT_HEADERS_SIZE; if (content_size > bufsz) { prerror("FLASH: content size > buffer size\n"); rc = OPAL_PARAMETER; goto out_free_ffs; } ffs_part_start += SECURE_BOOT_HEADERS_SIZE; rc = blocklevel_read(flash->bl, ffs_part_start, bufp, content_size); if (rc) { prerror("FLASH: failed to read content size %d" " %s partition, rc %d\n", content_size, name, rc); goto out_free_ffs; } if (subid == RESOURCE_SUBID_NONE) goto done_reading; rc = flash_subpart_info(bufp, content_size, ffs_part_size, NULL, subid, &offset, &content_size); if (rc) { prerror("FLASH: Failed to parse subpart info for %s\n", name); goto out_free_ffs; } bufp += offset; goto done_reading; } else /* stb_signed */ { /* * Back to the old way of doing things, no STB header. */ if (subid == RESOURCE_SUBID_NONE) { if (id == RESOURCE_ID_KERNEL || id == RESOURCE_ID_INITRAMFS) { /* * Because actualSize is a lie, we compute the * size of the BOOTKERNEL based on what the ELF * headers say. Otherwise we end up reading more * than we should */ content_size = sizeof_elf_from_hdr(buf); if (!content_size) { prerror("FLASH: Invalid ELF header part" " %s\n", name); rc = OPAL_RESOURCE; goto out_free_ffs; } } else { content_size = ffs_part_size; } if (content_size > bufsz) { prerror("FLASH: %s content size %d > " " buffer size %lu\n", name, content_size, bufsz); rc = OPAL_PARAMETER; goto out_free_ffs; } prlog(PR_DEBUG, "FLASH: computed %s size %u\n", name, content_size); rc = blocklevel_read(flash->bl, ffs_part_start, buf, content_size); if (rc) { prerror("FLASH: failed to read content size %d" " %s partition, rc %d\n", content_size, name, rc); goto out_free_ffs; } *len = content_size; goto done_reading; } BUILD_ASSERT(FLASH_SUBPART_HEADER_SIZE <= SECURE_BOOT_HEADERS_SIZE); rc = flash_subpart_info(bufp, SECURE_BOOT_HEADERS_SIZE, ffs_part_size, &ffs_part_size, subid, &offset, &content_size); if (rc) { prerror("FLASH: FAILED reading subpart info. rc=%d\n", rc); goto out_free_ffs; } *len = ffs_part_size; prlog(PR_DEBUG, "FLASH: Computed %s partition size: %u " "(subpart %u size %u offset %u)\n", name, ffs_part_size, subid, content_size, offset); /* * For a sub partition, we read the whole (computed) * partition, and then measure that. * Afterwards, we memmove() things back into place for * the caller. */ rc = blocklevel_read(flash->bl, ffs_part_start, buf, ffs_part_size); bufp += offset; } done_reading: /* * Verify and measure the retrieved PNOR partition as part of the * secure boot and trusted boot requirements */ secureboot_verify(id, buf, *len); trustedboot_measure(id, buf, *len); /* Find subpartition */ if (subid != RESOURCE_SUBID_NONE) { memmove(buf, bufp, content_size); *len = content_size; } status = true; out_free_ffs: ffs_close(ffs); out_unlock: unlock(&flash_lock); return status ? OPAL_SUCCESS : rc; }
uint32_t PNORInstruction::execute(ecmdDataBuffer & o_data, InstructionStatus & o_status, Handle ** io_handle) { uint32_t rc = 0; /* set the version of this instruction in the status */ o_status.instructionVersion = version; #if defined(CRONUS_SERVER_SIDE) /* check for any previous errors to report back */ if (error) { rc = o_status.rc = error; return rc; } switch(command) { /* * GET LIST OPERATION */ case PNORGETLIST: { #if defined(TESTING) printf("PNORGETLIST\n"); #endif std::string ffsDevice; ffsDevice = "/dev/mtdblock/sfc." + deviceString; #if defined(TESTING) printf("ffsData = ffs_open( \"%s\", 0x%X );\n", ffsDevice.c_str(), partitionOffset ); #else #if !defined(NO_GFW) off_t ffsDeviceOffset = partitionOffset; ffs_t *ffs = NULL; ffs = ffs_open( ffsDevice.c_str(), ffsDeviceOffset ); if ( ffs == NULL ) { std::ostringstream osse; osse << "PNORInstruction::execute SERVER DEBUG: Unable to open device " << ffsDevice << std::endl; o_status.errorMessage.append(osse.str()); osse.clear(); osse.str(std::string()); osse << "PNORInstruction::execute SERVER DEBUG: Listing partitions in image failed" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_DEVICE_FAIL_OPEN; break; } ffs_hdr_t *ffsHdr = ffs->hdr; #endif #endif Pnor_ffs_hdr *objHolder = new Pnor_ffs_hdr(); #if defined(TESTING) printf("transposing ffsData to internal Pnor_ffs_hdr object holder\n"); objHolder->magic = 0x1; objHolder->version = 0x2; objHolder->size = 1; objHolder->entry_size = 0x80; objHolder->entry_count = 2; objHolder->block_size = 0x1000; objHolder->block_count = 0x4000; objHolder->checksum = 0x3; Pnor_ffs_entry *objEntry = new Pnor_ffs_entry(); objEntry->base = 0x1fff; objEntry->size = 4096; objEntry->pid = 0; objEntry->id = 3; objEntry->type = 1; objEntry->flags = 0x0; objEntry->actual = 4096; objEntry->checksum = 0x43; objEntry->name = "HBBtest"; (objHolder->entries).push_back(objEntry); objEntry = new Pnor_ffs_entry(); objEntry->base = 0x0fff; objEntry->size = 8192; objEntry->pid = 0; objEntry->id = 2; objEntry->type = 3; objEntry->flags = 0x1; objEntry->actual = 8192; objEntry->checksum = 0x51; objEntry->name = "PNORtest"; (objHolder->entries).push_back(objEntry); #else #if !defined(NO_GFW) objHolder->magic = ffsHdr->magic; objHolder->version = ffsHdr->version; objHolder->size = ffsHdr->size; objHolder->entry_size = ffsHdr->entry_size; objHolder->entry_count = ffsHdr->entry_count; objHolder->block_size = ffsHdr->block_size; objHolder->block_count = ffsHdr->block_count; objHolder->checksum = ffsHdr->checksum; for( uint32_t idx = 0; idx < objHolder->entry_count; idx++ ) { Pnor_ffs_entry *objEntry = new Pnor_ffs_entry(); ffs_entry *ffsEntry = &(ffsHdr->entries[idx]); objEntry->base = ffsEntry->base; objEntry->size = ffsEntry->size; objEntry->pid = ffsEntry->pid; objEntry->id = ffsEntry->id; objEntry->type = ffsEntry->type; objEntry->flags = ffsEntry->flags; objEntry->actual = ffsEntry->actual; objEntry->checksum = ffsEntry->checksum; objEntry->name = ffsEntry->name; (objHolder->entries).push_back(objEntry); } #endif #endif uint32_t flattensize = objHolder->flattenSize(); uint32_t *flattenedffsData = new uint32_t[flattensize]; rc = objHolder->flatten( (uint8_t*) flattenedffsData, flattensize ); if ( rc ) { std::ostringstream osse; osse << "PNORInstruction::execute - flattenffsData failure" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_ERROR; return rc; } #if defined(TESTING) printf("Flattened objHolder of size %d\n", flattensize); #endif rc = o_data.setWordLength( flattensize ); if ( rc ) { std::ostringstream osse; osse << "PNORInstruction::execute - o_data.setWordLength(" << flattensize << ") failure" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_ERROR; return rc; } #if defined(TESTING) printf("o_data.getBitLength is %d\n", o_data.getBitLength()); #endif rc = o_data.insert( (uint8_t *)flattenedffsData, 0, (flattensize * 32), 0 ); if ( rc ) { std::ostringstream osse; osse << "PNORInstruction::execute - o_data.insert failure" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_ERROR; return rc; } #if defined(TESTING) printf("o_data.insert completed\n"); printf("\n%s\n", o_data.genHexLeftStr().c_str() ); #else #if !defined(NO_GFW) rc = ffs_close( ffs ); if ( rc ) { std::ostringstream osse; osse << "PNORInstruction::execute(" << InstructionCommandToString( command )<< ") - ffs_close failure rc(" << rc << ")" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_DEVICE_FAIL_CLOSE; break; } #endif #endif delete flattenedffsData; delete objHolder; rc = o_status.rc = SERVER_COMMAND_COMPLETE; break; } /* * GET OPERATION */ case PNORGET: { #if defined(TESTING) printf("PNORGET\n"); #endif std::string ffsDevice; ffsDevice = "/dev/mtdblock/sfc." + deviceString; #if defined(TESTING) printf("ffsData = ffs_open( \"%s\", 0x%X );\n", ffsDevice.c_str(), partitionOffset ); #else #if !defined(NO_GFW) off_t ffsDeviceOffset = partitionOffset; ffs_t *ffsData = NULL; ffsData = ffs_open( ffsDevice.c_str(), ffsDeviceOffset ); if ( ffsData == NULL ) { std::ostringstream osse; osse << "PNORInstruction::execute SERVER DEBUG: Unable to open device " << ffsDevice << std::endl; o_status.errorMessage.append(osse.str()); osse.clear(); osse.str(std::string()); osse << "PNORInstruction::execute SERVER DEBUG: Listing partitions in image failed" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_DEVICE_FAIL_OPEN; break; } #endif #endif #if defined(TESTING) printf("iterate over ffsData\n"); #else #if !defined(NO_GFW) //partitionEntry must match a partition entry within the ffsData, find it ffs_hdr_t *ffsHdr = ffsData->hdr; ffs_entry *myFoundEntry = NULL; for( uint32_t idx = 0; idx < ffsHdr->entry_count; idx++ ) { ffs_entry *ffsEntry = &(ffsHdr->entries[idx]); std::string entryName = ffsEntry->name; if ( entryName == partitionEntry ) { myFoundEntry = ffsEntry; break; } } if ( myFoundEntry == NULL ) { std::ostringstream osse; osse << "PNORInstruction::execute Unable to find a matching partition with name " << partitionEntry << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_PARTITION_NOT_FOUND; break; } #endif #endif #if defined(TESTING) printf("matched partition, now get data\n"); #else #if !defined(NO_GFW) // myFoundEntry points to the specific entry we want to read out if (global_server_debug) printf("myFoundEntry->type=%d, myFoundEntry->checksum=%.16X\n", myFoundEntry->type, myFoundEntry->checksum ); if ( myFoundEntry->type == FFS_TYPE_LOGICAL ) { std::ostringstream osse; osse << "PNORInstruction::execute Unable to get data from a logical partition for name " << partitionEntry << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_PARTITION_TYPE_INVALID; break; } else if ( myFoundEntry->actual == 0 ) { std::ostringstream osse; osse << "PNORInstruction::execute Size of partition is 0, not reading anything out for name " << partitionEntry << " size(" << myFoundEntry->actual << ")" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_PARTITION_EMPTY; break; } else { uint32_t bufferSize = ffsHdr->block_size * ffsData->buf_count; uint32_t *buffer = new uint32_t[bufferSize]; // uses partitionOffset uint32_t total = 0; uint32_t size = myFoundEntry->actual; off_t offset = 0; if (global_server_debug) printf("bufferSize(%d), total(%d), size(%d), offset(%d)\n", bufferSize, total, size, (uint32_t) offset); while ( 0 < size ) { size_t count = std::min( bufferSize, size ); if (global_server_debug) printf("name(%s), offset(%d), count(%d), size(%d), total(%d)\n", partitionEntry.c_str(), (uint32_t) offset, count, size, total); uint32_t bytesRead = ffs_entry_read( ffsData, partitionEntry.c_str(), buffer, offset, count ); if (global_server_debug) printf("post ffs_entry_read bytesRead=%d\n", bytesRead); if ( bytesRead < 0 ) { std::ostringstream osse; osse << "PNORInstruction::execute failure in ffs_entry_read " << partitionEntry << " offset(" << offset << ") count(" << count << ")" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_READ_ERROR; break; } else if ( bytesRead != count ) { std::ostringstream osse; osse << "PNORInstruction::execute failure to read enough data from partition " << partitionEntry << " expected(" << count << ") bytesRead(" << bytesRead << ")" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_READ_ERROR; break; } o_data.growBitLength( o_data.getBitLength() + (count*32) ); o_data.insert( buffer, total*32, count*32, 0 ); size -= count; total += count; offset += count; } // always attempt to close and only fallout on close if it fails // otherwise fallout on rc generated earlier rc = ffs_close( ffsData ); if (global_server_debug) printf("post ffs_close rc=%d\n", rc); if ( rc ) { std::ostringstream osse; osse << "PNORInstruction::execute(" << InstructionCommandToString( command )<< ") - ffs_close failure rc(" << rc << ")" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_DEVICE_FAIL_CLOSE; break; } } #endif #endif // make sure to set rc to COMMAND_COMPLETE if not already set // otherwise leave rc as is so it can be returned if ( rc == 0 ) { rc = o_status.rc = SERVER_COMMAND_COMPLETE; } break; } /* * PUT OPERATION */ case PNORPUT: { #if defined(TESTING) printf("PNORPUT\n"); #endif std::string ffsDevice; ffsDevice = "/dev/mtdblock/sfc." + deviceString; #if defined(TESTING) printf("ffsData = ffs_open( \"%s\", 0x%X );\n", ffsDevice.c_str(), partitionOffset ); #else #if !defined(NO_GFW) off_t ffsDeviceOffset = partitionOffset; ffs_t *ffsData = NULL; ffsData = ffs_open( ffsDevice.c_str(), ffsDeviceOffset ); if ( ffsData == NULL ) { std::ostringstream osse; osse << "PNORInstruction::execute SERVER DEBUG: Unable to open device " << ffsDevice << std::endl; o_status.errorMessage.append(osse.str()); osse.clear(); osse.str(std::string()); osse << "PNORInstruction::execute SERVER DEBUG: Listing partitions in image failed" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_DEVICE_FAIL_OPEN; break; } #endif #endif #if defined(TESTING) printf("iterate over ffsData\n"); #else #if !defined(NO_GFW) //partitionEntry must match a partition entry within the ffsData, find it ffs_hdr_t *ffsHdr = ffsData->hdr; ffs_entry *myFoundEntry = NULL; for( uint32_t idx = 0; idx < ffsHdr->entry_count; idx++ ) { ffs_entry *ffsEntry = &(ffsHdr->entries[idx]); std::string entryName = ffsEntry->name; if ( entryName == partitionEntry ) { myFoundEntry = ffsEntry; break; } } if ( myFoundEntry == NULL ) { std::ostringstream osse; osse << "PNORInstruction::execute Unable to find a matching partition with name " << partitionEntry << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_PARTITION_NOT_FOUND; break; } #endif #endif #if defined(TESTING) printf("matched partition, now get data\n"); #else #if !defined(NO_GFW) // myFoundEntry points to the specific entry we want to read out if (global_server_debug) printf("myFoundEntry->type=%d, myFoundEntry->checksum=%.16X\n", myFoundEntry->type, myFoundEntry->checksum ); if ( myFoundEntry->type == FFS_TYPE_LOGICAL ) { std::ostringstream osse; osse << "PNORInstruction::execute Unable to get data from a logical partition for name " << partitionEntry << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_PARTITION_TYPE_INVALID; break; } else if ( myFoundEntry->actual == 0 ) { std::ostringstream osse; osse << "PNORInstruction::execute Size of partition is 0, not reading anything out for name " << partitionEntry << " size(" << myFoundEntry->actual << ")" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_PARTITION_EMPTY; break; } else { uint32_t bufferSize = ffsHdr->block_size * ffsData->buf_count; if ( blockSize != 0 ) { bufferSize = blockSize; } uint32_t *buffer = new uint32_t[bufferSize]; uint32_t total = 0; uint32_t size = myFoundEntry->actual; off_t offset = 0; if (global_server_debug) printf("bufferSize(%d), total(%d), size(%d), offset(%d), o_data.getWordLength()(%d)\n", bufferSize, total, size, (uint32_t) offset, o_data.getWordLength()); if ( pnorFlags & INSTRUCTION_PNOR_FLAG_ERASE_PARTITION ) { // get first word from o_data (most likely 0) uint32_t myWord = o_data.getWord(0); // set the data buffer to the size of the partition o_data.setWordLength(size); // set each word in the buffer to myWord for( uint32_t idx=0; idx < size; idx++ ) { o_data.setWord( idx, myWord ); } if (global_server_debug) printf("erasing buffer with value (%d) for each word\n", myWord); } if ( o_data.getWordLength() != size ) { std::ostringstream osse; osse << "PNORInstruction::execute size mismatch for " << partitionEntry << " size(" << size << ") is not equal to input size(" << o_data.getWordLength() << ")" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_WRITE_ERROR; break; } while ( 0 < size ) { size_t count = std::min( bufferSize, size ); if (global_server_debug) printf("name(%s), offset(%d), count(%d), size(%d), total(%d)\n", partitionEntry.c_str(), (uint32_t) offset, count, size, total); // copy data from the ecmdDataBuffer into buffer for count (uint32_t's) memset( buffer, 0x0, bufferSize ); o_data.extract( buffer, total * 32, count * 32 ); uint32_t bytesWritten = ffs_entry_write( ffsData, partitionEntry.c_str(), buffer, offset, count ); uint32_t fsyncRc = ffs_fsync( ffsData ); if (global_server_debug) printf("post ffs_entry_write bytesWritten=%d\n", bytesWritten); if ( bytesWritten < 0 ) { std::ostringstream osse; osse << "PNORInstruction::execute failure in ffs_entry_write " << partitionEntry << " offset(" << offset << ") count(" << count << ")" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_WRITE_ERROR; break; } else if ( bytesWritten != count ) { std::ostringstream osse; osse << "PNORInstruction::execute failure to read enough data from partition " << partitionEntry << " expected(" << count << ") bytesWritten(" << bytesWritten << ")" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_WRITE_ERROR; break; } if ( fsyncRc < 0 ) { std::ostringstream osse; osse << "PNORInstruction::execute failure in ffs_fsync " << partitionEntry << " fsyncRc(" << fsyncRc << ")" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_FSYNC_ERROR; break; } size -= count; total += count; offset += count; } // always attempt to close and only fallout on close if it fails // otherwise fallout on rc generated earlier rc = ffs_close( ffsData ); if (global_server_debug) printf("post ffs_close rc=%d\n", rc); if ( rc ) { std::ostringstream osse; osse << "PNORInstruction::execute(" << InstructionCommandToString( command )<< ") - ffs_close failure rc(" << rc << ")" << std::endl; o_status.errorMessage.append(osse.str()); rc = o_status.rc = SERVER_PNOR_DEVICE_FAIL_CLOSE; break; } } #endif #endif // make sure to set rc to COMMAND_COMPLETE if not already set // otherwise leave rc as is so it can be returned if ( rc == 0 ) { rc = o_status.rc = SERVER_COMMAND_COMPLETE; } break; } default: rc = o_status.rc = SERVER_COMMAND_NOT_SUPPORTED; break; } #endif // CRONUS_SERVER_SIDE return rc; }