diff options
| author | Martin Peschke <mpeschke@de.ibm.com> | 2017-04-08 19:02:59 +0200 |
|---|---|---|
| committer | Joshua Hunsberger <jahunsbe@us.ibm.com> | 2017-10-23 17:35:36 -0500 |
| commit | cf1e2b9514b8f04a3efd4cb9f0ad0246cfdba91f (patch) | |
| tree | de2eab08bf71e4b5fa029721dc167b5cc7f70389 /import/chips/p9/utils | |
| parent | 514f6623a16a3f3f1cc713385601bca116baa858 (diff) | |
| download | talos-hcode-cf1e2b9514b8f04a3efd4cb9f0ad0246cfdba91f.tar.gz talos-hcode-cf1e2b9514b8f04a3efd4cb9f0ad0246cfdba91f.zip | |
p9_dd_container: simple generic standalone DD level container
Change-Id: I4c9d8cb28d4ae6a8b21c87ebaad07c1fd7163b85
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/39588
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Claus M. Olsen <cmolsen@us.ibm.com>
Reviewed-by: Sumit Kumar <sumit_kumar@in.ibm.com>
Reviewed-by: Martin Peschke <mpeschke@de.ibm.com>
Diffstat (limited to 'import/chips/p9/utils')
| -rw-r--r-- | import/chips/p9/utils/imageProcs/p9_dd_container.c | 262 | ||||
| -rw-r--r-- | import/chips/p9/utils/imageProcs/p9_dd_container.h | 94 | ||||
| -rw-r--r-- | import/chips/p9/utils/imageProcs/p9_dd_container.mk | 26 | ||||
| -rw-r--r-- | import/chips/p9/utils/imageProcs/p9_dd_container_tool.c | 356 | ||||
| -rw-r--r-- | import/chips/p9/utils/imageProcs/p9_dd_container_tool.mk | 29 |
5 files changed, 767 insertions, 0 deletions
diff --git a/import/chips/p9/utils/imageProcs/p9_dd_container.c b/import/chips/p9/utils/imageProcs/p9_dd_container.c new file mode 100644 index 00000000..340de207 --- /dev/null +++ b/import/chips/p9/utils/imageProcs/p9_dd_container.c @@ -0,0 +1,262 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/utils/imageProcs/p9_dd_container.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#include <stdint.h> +#include <stddef.h> +#include <stdlib.h> +#include <endian.h> +#include <string.h> +#include <stdio.h> + +#include "p9_dd_container.h" + +int p9_dd_validate(struct p9_dd_cont* i_cont) +{ + if (!i_cont) + { + return P9_DD_FAILURE_DOES_NOT_EXIST; + } + + if (be32toh(i_cont->iv_magic) != P9_DD_CONTAINER_MAGIC) + { + return P9_DD_FAILURE_BROKEN; + } + + // may want to check here for holes or overlap as to stored blocks + + return P9_DD_SUCCESS; +} + +// iterates through all dd level blocks +struct p9_dd_block* p9_dd_next(struct p9_dd_iter* io_iter) +{ + struct p9_dd_block* block; + + if (!io_iter || + !io_iter->iv_cont || + io_iter->iv_idx >= io_iter->iv_cont->iv_num) + { + return NULL; + } + + block = &(io_iter->iv_cont->iv_blocks)[io_iter->iv_idx]; + io_iter->iv_idx++; + + return block; +} + +uint8_t* p9_dd_addr(struct p9_dd_cont* i_cont, uint32_t i_offset) +{ + return (uint8_t*)i_cont + i_offset; +} + +void p9_dd_betoh(struct p9_dd_block* i_block_be, + struct p9_dd_block* io_block_he) +{ + io_block_he->iv_offset = be32toh(i_block_be->iv_offset); + io_block_he->iv_size = be32toh(i_block_be->iv_size); + io_block_he->iv_dd = i_block_be->iv_dd; +} + +// returns address of dd level content (without meta data) +int p9_dd_get(uint8_t* i_cont, uint8_t i_dd, uint8_t** o_buf, uint32_t* o_size) +{ + struct p9_dd_cont* cont = (struct p9_dd_cont*)i_cont; + struct p9_dd_iter iter = P9_DD_ITER_INIT(cont); + struct p9_dd_block* block; + struct p9_dd_block block_he; + int rc; + + rc = p9_dd_validate(cont); + + if (rc != P9_DD_SUCCESS) + { + return rc; + } + + while ((block = p9_dd_next(&iter))) + { + if (block->iv_dd == i_dd) + { + p9_dd_betoh(block, &block_he); + *o_buf = p9_dd_addr(cont, block_he.iv_offset); + *o_size = block_he.iv_size; + return P9_DD_SUCCESS; + } + } + + return P9_DD_FAILURE_NOT_FOUND; +} + +uint32_t p9_dd_size_meta(struct p9_dd_cont* i_cont) +{ + return (i_cont ? + (sizeof(struct p9_dd_cont) + + sizeof(struct p9_dd_block) * i_cont->iv_num) : + 0); +} + +// assumes only API (p9_dd_add()) used to create container, +// that is, last block header points to block with biggest offset +uint32_t p9_dd_size(struct p9_dd_cont* i_cont) +{ + struct p9_dd_block* last; + + if (!i_cont) + { + return 0; + } + + if (!i_cont->iv_num) + { + return p9_dd_size_meta(i_cont); + } + + last = &(i_cont->iv_blocks)[i_cont->iv_num - 1]; + + return be32toh(last->iv_offset) + be32toh(last->iv_size); +} + +struct p9_dd_cont* p9_dd_create(void) +{ + struct p9_dd_cont* cont; + + cont = malloc(sizeof(struct p9_dd_cont)); + + if (!cont) + { + return cont; + } + + cont->iv_magic = htobe32(P9_DD_CONTAINER_MAGIC); + cont->iv_num = 0; + + return cont; +} + +// enlarges (reallocates) container and copies dd level block into container +int p9_dd_add( + uint8_t** io_cont, uint32_t* o_cont_size, uint8_t i_dd, + uint8_t* i_buf, uint32_t i_buf_size) +{ + struct p9_dd_cont* cont = (struct p9_dd_cont*)*io_cont; + + uint8_t* dupl_buf; + uint32_t dupl_size; + + uint32_t enlarged; + + int rc; + + uint8_t* others_addr_new; + uint8_t* others_addr_old; + uint32_t others_size; + struct p9_dd_block* others_block; + + uint8_t* this_addr; + uint32_t this_offs; + struct p9_dd_block* this_block; + + struct p9_dd_iter iter = P9_DD_ITER_INIT(NULL); + + // handle duplicates and initial setup of empty container + rc = p9_dd_get(*io_cont, i_dd, &dupl_buf, &dupl_size); + + switch (rc) + { + case P9_DD_FAILURE_NOT_FOUND : + break; + + case P9_DD_FAILURE_DOES_NOT_EXIST : + cont = p9_dd_create(); + + if (!cont) + { + return P9_DD_FAILURE_NOMEM; + } + + break; + + case P9_DD_SUCCESS : + return P9_DD_FAILURE_DUPLICATE; + + default : + return rc; + } + + // size of enlarged container + enlarged = p9_dd_size(cont) + sizeof(struct p9_dd_block) + i_buf_size; + + // re-allocate to enlarge container (content is retained and consistent) + cont = realloc(cont, enlarged); + + if (!cont) + { + return P9_DD_FAILURE_NOMEM; + } + + // offsets and size of existing bufs + others_addr_old = p9_dd_addr(cont, p9_dd_size_meta(cont)); + others_addr_new = others_addr_old + sizeof(struct p9_dd_block); + others_size = p9_dd_size(cont) - p9_dd_size_meta(cont); + + // meta data, offset and address of new buf + this_block = (struct p9_dd_block*)others_addr_old; + this_offs = p9_dd_size(cont) + sizeof(struct p9_dd_block); + this_addr = p9_dd_addr(cont, this_offs); + + // fix offsets of existing bufs + iter.iv_cont = cont; + + while ((others_block = p9_dd_next(&iter))) + { + others_block->iv_offset = + htobe32(be32toh(others_block->iv_offset) + + sizeof(struct p9_dd_block)); + } + + // move existing bufs + memmove(others_addr_new, others_addr_old, others_size); + + // copy new buf into container + memcpy(this_addr, i_buf, i_buf_size); + + // fill in meta data for new buf + memset(this_block, sizeof(struct p9_dd_block), 0); + this_block->iv_offset = htobe32(this_offs); + this_block->iv_size = htobe32(i_buf_size); + this_block->iv_dd = i_dd; + this_block->iv_reserved[0] = 0; + this_block->iv_reserved[1] = 0; + this_block->iv_reserved[2] = 0; + + // increase number off DD level blocks in container + (cont)->iv_num++; + + *io_cont = (uint8_t*)cont; + *o_cont_size = enlarged; + + return P9_DD_SUCCESS; +} diff --git a/import/chips/p9/utils/imageProcs/p9_dd_container.h b/import/chips/p9/utils/imageProcs/p9_dd_container.h new file mode 100644 index 00000000..6a373587 --- /dev/null +++ b/import/chips/p9/utils/imageProcs/p9_dd_container.h @@ -0,0 +1,94 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/utils/imageProcs/p9_dd_container.h $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#ifndef _P9_DD_CONTAINER_H_ +#define _P9_DD_CONTAINER_H_ + +#include <stdint.h> + +#define P9_DD_CONTAINER_MAGIC 0x4444434F // "DDCO" + +#define P9_DD_SUCCESS 0 +#define P9_DD_FAILURE_BROKEN 1 +#define P9_DD_FAILURE_NOMEM 2 +#define P9_DD_FAILURE_NOT_FOUND 3 +#define P9_DD_FAILURE_DOES_NOT_EXIST 4 +#define P9_DD_FAILURE_DUPLICATE 5 + +// header for each dd level block inside container +struct p9_dd_block +{ + uint32_t iv_offset; + uint32_t iv_size; + uint8_t iv_dd; + uint8_t iv_reserved[3]; +}; + +// container header +struct p9_dd_cont +{ + uint32_t iv_magic; + uint8_t iv_num; + uint8_t iv_reserved[3]; + struct p9_dd_block iv_blocks[0]; +}; + +// iterator that can be used to iterate through all dd level blocks +struct p9_dd_iter +{ + struct p9_dd_cont* iv_cont; + uint8_t iv_idx; +}; + +// initialisation of iterator +#define P9_DD_ITER_INIT(dd_cont) { .iv_cont = (dd_cont), .iv_idx = 0 } + +#ifdef __cplusplus +extern "C" { +#endif + +// validates container +int p9_dd_validate(struct p9_dd_cont* i_cont); + +void p9_dd_betoh(struct p9_dd_block* i_block_be, + struct p9_dd_block* io_block_he); + +// iterates through all dd level blocks +struct p9_dd_block* p9_dd_next(struct p9_dd_iter* io_iter); + +// returns address of dd level content (without meta data) +int p9_dd_get( + uint8_t* i_cont, uint8_t i_dd, uint8_t** o_buf, uint32_t* o_size); + +// enlarges (reallocates) container and copies dd level block into container +int p9_dd_add( + uint8_t** io_cont, uint32_t* o_cont_size, uint8_t i_dd, + uint8_t* i_buf, uint32_t i_buf_size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/import/chips/p9/utils/imageProcs/p9_dd_container.mk b/import/chips/p9/utils/imageProcs/p9_dd_container.mk new file mode 100644 index 00000000..f08211ca --- /dev/null +++ b/import/chips/p9/utils/imageProcs/p9_dd_container.mk @@ -0,0 +1,26 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: import/chips/p9/utils/imageProcs/p9_dd_container.mk $ +# +# OpenPOWER HCODE Project +# +# COPYRIGHT 2016,2017 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +PROCEDURE=p9_dd_container +$(call BUILD_PROCEDURE) diff --git a/import/chips/p9/utils/imageProcs/p9_dd_container_tool.c b/import/chips/p9/utils/imageProcs/p9_dd_container_tool.c new file mode 100644 index 00000000..016796e4 --- /dev/null +++ b/import/chips/p9/utils/imageProcs/p9_dd_container_tool.c @@ -0,0 +1,356 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/utils/imageProcs/p9_dd_container_tool.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <getopt.h> +#include <stdbool.h> +#include <stdlib.h> +#include <unistd.h> + +#include "p9_dd_container.h" + +bool debug = false; + +#define DEBUG(_fmt_, _args_...) \ + if (debug) \ + { \ + printf(_fmt_, ##_args_); \ + } + +enum commands +{ + COMMAND_UNDEF, + COMMAND_ADD, + COMMAND_GET, + COMMAND_LIST +}; + +const char* usage = + "adds DD level block to container, and creates container, if needed\n" + "\n" + "Usage:\n" + " p9_dd_container_tool [options]\n" + " --command add|get|list\n" + " --dd <num> DD level number (hexadecimal)\n" + " --block <file name> DD level block to be added\n" + " --cont <file name> DD level block container to be enlarged/shown\n" + " --help this information\n" + " --debug enable debug output\n" + "\n" + "Examples:\n" + " p9_dd_container_tool\n" + " --command add\n" + " --dd 0x10\n" + " --block output/images/cme/p9n/dd10/cme.bin\n" + " --cont output/images/cme/hcode.bin\n" + " p9_dd_container_tool\n" + " --command get\n" + " --cont output/images/cme/hcode.bin\n" + " --dd 0x10\n" + " p9_dd_container_tool\n" + " --command list\n" + " --cont output/images/cme/hcode.bin\n" + "\n" + "If the DD level container file already exists, the tool attempts\n" + "to add the new DD level block. Otherwise a new DD level container\n" + "is created and a new output file is written.\n" + "\n" + "The tool checks for duplicates. That means, a DD level block\n" + "is to be added is rejected if another block for the same DD\n" + "level number already exists.\n"; + +static const struct option options[] = +{ + {"command", required_argument, NULL, 'c'}, + {"dd", required_argument, NULL, 'n'}, + {"block", required_argument, NULL, 'b'}, + {"cont", required_argument, NULL, 'o'}, + {"help", no_argument, NULL, 'h'}, + {"debug", no_argument, NULL, 'd'}, +}; + +static const char* optionstr = "c:nbo:h:d"; + +int p9_dd_tool_read(uint8_t** buf, uint32_t* size, char* fn, int mandatory) +{ + FILE* fp; + uint32_t read; + + fp = fopen(fn, "r"); + + if (!fp) + { + if (mandatory) + { + printf("failed to open %s for reading\n", fn); + exit(-1); + } + + *buf = NULL; + *size = 0; + return *size; + } + + fseek(fp, 0, SEEK_END); + *size = ftell(fp); + + if (*size) + { + fseek(fp, 0, SEEK_SET); + *buf = malloc(*size); + + if (!*buf) + { + printf("failed to allocate buffer\n"); + fclose(fp); + exit(-1); + } + + read = fread(*buf, 1, *size, fp); + + if (read != *size) + { + printf("failed to read %s\n", fn); + exit(-1); + } + } + + fclose(fp); + + return *size; +} + +int p9_dd_tool_write(uint8_t* buf, uint32_t size, char* fn) +{ + FILE* fp; + uint32_t written; + + fp = fopen(fn, "w+"); + + if (!fp) + { + printf("failed to open %s for writing\n", fn); + exit(-1); + } + + written = fwrite(buf, 1, size, fp); + + if (written != size) + { + printf("failed to write to %s\n", fn); + exit(-1); + } + + fclose(fp); + return size; +} + +int p9_dd_tool_add(int dd, char* fn_block, char* fn_cont) +{ + uint32_t block_size; + uint32_t cont_size; + uint8_t* block; + uint8_t* cont; + int rc = 0; + + p9_dd_tool_read(&block, &block_size, fn_block, 1); + p9_dd_tool_read(&cont, &cont_size, fn_cont, 0); + + if (block || block_size) + { + rc = p9_dd_add(&cont, &cont_size, dd, block, block_size); + + if (rc == P9_DD_SUCCESS) + { + rc = p9_dd_tool_write(cont, cont_size, fn_cont); + } + else + { + printf("failed, p9_dd_add returned %d\n", rc); + } + } + + free(block); + free(cont); + + return rc; +} + +int p9_dd_tool_get(int dd, char* fn_block, char* fn_cont) +{ + uint32_t block_size; + uint32_t cont_size; + uint8_t* block; + uint8_t* cont; + int rc = 0; + + p9_dd_tool_read(&cont, &cont_size, fn_cont, 1); + + rc = p9_dd_get(cont, dd, &block, &block_size); + + if (rc == P9_DD_SUCCESS) + { + rc = p9_dd_tool_write(block, block_size, fn_block); + } + else + { + printf("failed, p9_dd_get returned %d\n", rc); + } + + free(cont); + + return rc; +} + +int p9_dd_tool_list(char* fn_cont) +{ + uint32_t cont_size; + uint8_t* cont; + struct p9_dd_iter iter = P9_DD_ITER_INIT(NULL); + struct p9_dd_block* block; + struct p9_dd_block block_he; + + p9_dd_tool_read(&cont, &cont_size, fn_cont, 1); + iter.iv_cont = (struct p9_dd_cont*)cont; + + while ((block = p9_dd_next(&iter))) + { + p9_dd_betoh(block, &block_he); + printf("block: dd=0x%x size=%d\n", block_he.iv_dd, block_he.iv_size); + } + + free(cont); + + return 0; +} + +int main(int argc, char* argv[]) +{ + char* fn_block = NULL; + char* fn_cont = NULL; + int dd = 0; + int command = COMMAND_UNDEF; + int option = -1; + + if (argc == 1) + { + printf("%s", usage); + exit(-1); + } + + while (-1 != (option = getopt_long(argc, argv, optionstr, options, NULL))) + { + switch (option) + { + case 'c' : + if (!strcmp(optarg, "add")) + { + command = COMMAND_ADD; + } + else if (!strcmp(optarg, "get")) + { + command = COMMAND_GET; + } + else if (!strcmp(optarg, "list")) + { + command = COMMAND_LIST; + } + + break; + + case 'n' : + if (sscanf(optarg, "0x%x", &dd) != 1) + { + printf("%s", usage); + exit(-1); + } + + break; + + case 'b' : + fn_block = strdup(optarg); + break; + + case 'o' : + if (fn_cont) + { + printf("%s", usage); + exit(-1); + } + + fn_cont = strdup(optarg); + break; + + case 'd' : + debug = true; + break; + + case 'h' : + printf("%s", usage); + exit(0); + + default : + printf("%s", usage); + exit(-1); + } + + switch (command) + { + case COMMAND_LIST : + if (fn_cont) + { + return p9_dd_tool_list(fn_cont); + } + + break; + + case COMMAND_ADD : + if (fn_cont && fn_block && dd) + { + p9_dd_tool_add(dd, fn_block, fn_cont); + dd = 0; + free(fn_block); + fn_block = NULL; + } + + break; + + case COMMAND_GET : + if (fn_cont && fn_block && dd) + { + p9_dd_tool_get(dd, fn_block, fn_cont); + dd = 0; + free(fn_block); + fn_block = NULL; + } + + break; + } + } + + return 0; +} diff --git a/import/chips/p9/utils/imageProcs/p9_dd_container_tool.mk b/import/chips/p9/utils/imageProcs/p9_dd_container_tool.mk new file mode 100644 index 00000000..063aee50 --- /dev/null +++ b/import/chips/p9/utils/imageProcs/p9_dd_container_tool.mk @@ -0,0 +1,29 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: import/chips/p9/utils/imageProcs/p9_dd_container_tool.mk $ +# +# OpenPOWER HCODE Project +# +# COPYRIGHT 2017 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +EXE = p9_dd_container_tool +OBJS += $(EXE).o +$(EXE)_DEPLIBS += p9_dd_container +$(call BUILD_EXE) |

