| /**************************************************************************** |
| * fs/partition/fs_txtable.c |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you 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. |
| * |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <ctype.h> |
| #include <fcntl.h> |
| #include <string.h> |
| #include <stdio.h> |
| |
| #include <nuttx/kmalloc.h> |
| |
| #include "partition.h" |
| #include "fs_heap.h" |
| |
| /**************************************************************************** |
| * Pre-processor Definitions |
| ****************************************************************************/ |
| |
| #ifndef CONFIG_TXTABLE_DEFAULT_PARTITION_PATH |
| # define CONFIG_TXTABLE_DEFAULT_PARTITION_PATH "" |
| #endif |
| |
| #define TXTABLE_MAGIC "TXTABLE0" |
| #define TXTABLE_LENGTH (state->erasesize + 1) |
| |
| /**************************************************************************** |
| * Public Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: parse_txtable_partition |
| * |
| * Description: |
| * parse the TXTABLE partition txtable. |
| * |
| * Input Parameters: |
| * state - The partition txtable state |
| * handler - The function to be called for each found partition |
| * arg - A caller provided value to return with the handler |
| * |
| * Returned Value: |
| * A negated errno value is returned on a failure; Otherwise success |
| * |
| ****************************************************************************/ |
| |
| int parse_txtable_partition(FAR struct partition_state_s *state, |
| partition_handler_t handler, |
| FAR void *arg) |
| { |
| FAR char *save_ptr; |
| FAR char *token; |
| FAR struct partition_s *part; |
| size_t blkpererase; |
| size_t lasteraseblk; |
| int ret = OK; |
| int i; |
| int j; |
| |
| /* Allocate memory for table of parsed and raw */ |
| |
| part = fs_heap_malloc(CONFIG_TXTABLE_PARTITION_MAX_NUM * |
| sizeof(struct partition_s) + |
| TXTABLE_LENGTH); |
| if (part == NULL) |
| { |
| return -ENOMEM; |
| } |
| |
| memset(part, 0, CONFIG_TXTABLE_PARTITION_MAX_NUM * |
| sizeof(struct partition_s)); |
| |
| /* TXTABLE locate in the last erase block */ |
| |
| blkpererase = state->erasesize / state->blocksize; |
| lasteraseblk = state->nblocks - blkpererase; |
| |
| for (i = 0; i <= CONFIG_TXTABLE_DEFAULT_PARTITION; i++) |
| { |
| token = (FAR char *)(part + CONFIG_TXTABLE_PARTITION_MAX_NUM); |
| |
| memset(token, 0, TXTABLE_LENGTH); |
| |
| if (i == 0) |
| { |
| ret = read_partition_block(state, token, lasteraseblk, |
| blkpererase); |
| if (ret < 0) |
| { |
| continue; |
| } |
| } |
| else |
| { |
| struct file f; |
| |
| ret = file_open(&f, CONFIG_TXTABLE_DEFAULT_PARTITION_PATH, |
| O_RDONLY); |
| if (ret < 0) |
| { |
| continue; |
| } |
| |
| ret = file_read(&f, token, state->erasesize); |
| file_close(&f); |
| if (ret < 0) |
| { |
| continue; |
| } |
| } |
| |
| /* Parsing data of partition table */ |
| |
| token = strtok_r(token, "\n", &save_ptr); |
| if (token == NULL || |
| strncmp(token, TXTABLE_MAGIC, strlen(TXTABLE_MAGIC)) != 0) |
| { |
| save_ptr = NULL; |
| ret = -EFTYPE; |
| continue; |
| } |
| |
| break; |
| } |
| |
| if (ret < 0) |
| { |
| goto out; |
| } |
| |
| for (i = 0; i < CONFIG_TXTABLE_PARTITION_MAX_NUM - 1; i++) |
| { |
| token = strtok_r(NULL, "\n", &save_ptr); |
| if (token == NULL || !isalnum(token[0])) |
| { |
| break; |
| } |
| |
| ret = sscanf(token, "%s %zx %zx", |
| part[i].name, |
| &part[i].nblocks, |
| &part[i].firstblock); |
| if (ret < 0) |
| { |
| goto out; |
| } |
| |
| part[i].index = i; |
| part[i].firstblock /= state->blocksize; |
| part[i].nblocks /= state->blocksize; |
| part[i].blocksize = state->blocksize; |
| } |
| |
| for (j = 0; j < i; j++) |
| { |
| if (!part[j].firstblock && j > 0) |
| { |
| part[j].firstblock = part[j - 1].firstblock + |
| part[j - 1].nblocks; |
| } |
| |
| if (!part[j].nblocks) |
| { |
| if (j + 1 < i) |
| { |
| if (part[j + 1].firstblock) |
| { |
| part[j].nblocks = part[j + 1].firstblock - |
| part[j].firstblock; |
| } |
| } |
| else |
| { |
| part[j].nblocks = state->nblocks - part[j].firstblock - |
| blkpererase; |
| } |
| } |
| |
| /* Reserved for txtable */ |
| |
| if (j + 1 == i && |
| part[j].firstblock + part[j].nblocks > lasteraseblk) |
| { |
| part[j].nblocks = lasteraseblk - part[j].firstblock; |
| } |
| |
| /* Notify the caller */ |
| |
| handler(&part[j], arg); |
| } |
| |
| /* Pseudo partition for the last eraseblock */ |
| |
| strlcpy(part[j].name, "txtable", sizeof(part[j].name)); |
| part[j].index = j; |
| part[j].firstblock = lasteraseblk; |
| part[j].nblocks = blkpererase; |
| part[j].blocksize = state->blocksize; |
| |
| handler(&part[j], arg); |
| |
| out: |
| fs_heap_free(part); |
| return ret; |
| } |