fs/nffs/src/nffs_format.c (121 lines of code) (raw):

/* * 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. */ #include <assert.h> #include <string.h> #include "hal/hal_flash.h" #include "nffs_priv.h" #include "nffs/nffs.h" /** * Turns a scratch area into a non-scratch area. If the specified area is not * actually a scratch area, this function falls back to a slower full format * operation. */ int nffs_format_from_scratch_area(uint8_t area_idx, uint8_t area_id) { struct nffs_disk_area disk_area; int rc; assert(area_idx < nffs_num_areas); STATS_INC(nffs_stats, nffs_readcnt_format); rc = nffs_flash_read(area_idx, 0, &disk_area, sizeof disk_area); if (rc != 0) { return rc; } nffs_areas[area_idx].na_id = area_id; if (!nffs_area_is_scratch(&disk_area)) { rc = nffs_format_area(area_idx, 0); if (rc != 0) { return rc; } } else { disk_area.nda_id = area_id; rc = nffs_flash_write(area_idx, NFFS_AREA_OFFSET_ID, &disk_area.nda_id, sizeof disk_area.nda_id); if (rc != 0) { return rc; } } return 0; } /** * Formats a single scratch area. */ int nffs_format_area(uint8_t area_idx, int is_scratch) { struct nffs_disk_area disk_area; struct nffs_area *area; uint32_t write_len; int rc; area = nffs_areas + area_idx; rc = hal_flash_erase(area->na_flash_id, area->na_offset, area->na_length); if (rc != 0) { return FS_EHW; } area->na_cur = 0; nffs_area_to_disk(area, &disk_area); if (is_scratch) { nffs_areas[area_idx].na_id = NFFS_AREA_ID_NONE; write_len = sizeof disk_area - sizeof disk_area.nda_id; } else { write_len = sizeof disk_area; } rc = nffs_flash_write(area_idx, 0, &disk_area.nda_magic, write_len); if (rc != 0) { return rc; } return 0; } /** * Erases all the specified areas and initializes them with a clean nffs * file system. * * @param area_descs The set of areas to format. * * @return 0 on success; * nonzero on failure. */ int nffs_format_full(const struct nffs_area_desc *area_descs) { int rc; int i; /* Start from a clean state. */ nffs_misc_reset(); /* Select largest area to be the initial scratch area. */ nffs_scratch_area_idx = 0; for (i = 1; area_descs[i].nad_length != 0; i++) { if (i >= NFFS_MAX_AREAS) { rc = FS_EINVAL; goto err; } if (area_descs[i].nad_length > area_descs[nffs_scratch_area_idx].nad_length) { nffs_scratch_area_idx = i; } } rc = nffs_misc_set_num_areas(i); if (rc != 0) { goto err; } for (i = 0; i < nffs_num_areas; i++) { nffs_areas[i].na_offset = area_descs[i].nad_offset; nffs_areas[i].na_length = area_descs[i].nad_length; nffs_areas[i].na_flash_id = area_descs[i].nad_flash_id; nffs_areas[i].na_cur = 0; nffs_areas[i].na_gc_seq = 0; if (i == nffs_scratch_area_idx) { nffs_areas[i].na_id = NFFS_AREA_ID_NONE; } else { nffs_areas[i].na_id = i; } rc = nffs_format_area(i, i == nffs_scratch_area_idx); if (rc != 0) { goto err; } } rc = nffs_misc_validate_scratch(); if (rc != 0) { goto err; } /* Create root directory. */ rc = nffs_file_new(NULL, "", 0, 1, &nffs_root_dir); if (rc != 0) { goto err; } /* Create "lost+found" directory. */ rc = nffs_misc_create_lost_found_dir(); if (rc != 0) { goto err; } rc = nffs_misc_validate_root_dir(); if (rc != 0) { goto err; } rc = nffs_misc_set_max_block_data_len(0); if (rc != 0) { goto err; } nffs_current_area_descs = (struct nffs_area_desc*) area_descs; return 0; err: nffs_misc_reset(); return rc; }