/** * 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; } return 0; err: nffs_misc_reset(); return rc; }
/** * Searches for a valid nffs file system among the specified areas. This * function succeeds if a file system is detected among any subset of the * supplied areas. If the area set does not contain a valid file system, * a new one can be created via a call to nffs_format(). * * @param area_descs The area set to search. This array must be * terminated with a 0-length area. * * @return 0 on success; * FS_ECORRUPT if no valid file system was detected; * other nonzero on error. */ int nffs_restore_full(const struct nffs_area_desc *area_descs) { struct nffs_disk_area disk_area; int cur_area_idx; int use_area; int rc; int i; /* Start from a clean state. */ rc = nffs_misc_reset(); if (rc) { return rc; } nffs_restore_largest_block_data_len = 0; /* Read each area from flash. */ for (i = 0; area_descs[i].nad_length != 0; i++) { if (i > NFFS_MAX_AREAS) { rc = FS_EINVAL; goto err; } rc = nffs_restore_detect_one_area(area_descs[i].nad_flash_id, area_descs[i].nad_offset, &disk_area); switch (rc) { case 0: use_area = 1; break; case FS_ECORRUPT: use_area = 0; break; default: goto err; } if (use_area) { if (disk_area.nda_id == NFFS_AREA_ID_NONE && nffs_scratch_area_idx != NFFS_AREA_ID_NONE) { /* Don't allow more than one scratch area. */ use_area = 0; } } if (use_area) { /* Populate RAM with a representation of this area. */ cur_area_idx = nffs_num_areas; rc = nffs_misc_set_num_areas(nffs_num_areas + 1); if (rc != 0) { goto err; } nffs_areas[cur_area_idx].na_offset = area_descs[i].nad_offset; nffs_areas[cur_area_idx].na_length = area_descs[i].nad_length; nffs_areas[cur_area_idx].na_flash_id = area_descs[i].nad_flash_id; nffs_areas[cur_area_idx].na_gc_seq = disk_area.nda_gc_seq; nffs_areas[cur_area_idx].na_id = disk_area.nda_id; if (disk_area.nda_id == NFFS_AREA_ID_NONE) { nffs_areas[cur_area_idx].na_cur = NFFS_AREA_OFFSET_ID; nffs_scratch_area_idx = cur_area_idx; } else { nffs_areas[cur_area_idx].na_cur = sizeof (struct nffs_disk_area); nffs_restore_area_contents(cur_area_idx); } } } /* All areas have been restored from flash. */ if (nffs_scratch_area_idx == NFFS_AREA_ID_NONE) { /* No scratch area. The system may have been rebooted in the middle of * a garbage collection cycle. Look for a candidate scratch area. */ rc = nffs_restore_corrupt_scratch(); if (rc != 0) { if (rc == FS_ENOENT) { rc = FS_ECORRUPT; } goto err; } } /* Ensure this file system contains a valid scratch area. */ rc = nffs_misc_validate_scratch(); if (rc != 0) { goto err; } /* Make sure the file system contains a valid root directory. */ rc = nffs_misc_validate_root_dir(); if (rc != 0) { goto err; } /* Ensure there is a "/lost+found" directory. */ rc = nffs_misc_create_lost_found_dir(); if (rc != 0) { goto err; } /* Delete from RAM any objects that were invalidated when subsequent areas * were restored. */ nffs_restore_sweep(); /* Set the maximum data block size according to the size of the smallest * area. */ rc = nffs_misc_set_max_block_data_len(nffs_restore_largest_block_data_len); if (rc != 0) { goto err; } return 0; err: nffs_misc_reset(); return rc; }