297
282
/** Get cluster from the first FAT.
299
284
* @param bs Buffer holding the boot sector for the file system.
300
* @param devmap_handle Device handle for the file system.
301
* @param clst Cluster which to get.
302
* @param value Output argument holding the value of the cluster.
304
* @return EOK or a negative error code.
307
fat_get_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
308
fat_cluster_t clst, fat_cluster_t *value)
314
rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
315
(clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
318
cp = (fat_cluster_t *)b->data +
319
clst % (BPS(bs) / sizeof(fat_cluster_t));
320
*value = uint16_t_le2host(*cp);
326
/** Set cluster in one instance of FAT.
328
* @param bs Buffer holding the boot sector for the file system.
329
* @param devmap_handle Device handle for the file system.
330
* @param fatno Number of the FAT instance where to make the change.
331
* @param clst Cluster which is to be set.
332
* @param value Value to set the cluster with.
334
* @return EOK on success or a negative error code.
337
fat_set_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
338
fat_cluster_t clst, fat_cluster_t value)
344
assert(fatno < FATCNT(bs));
345
rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
346
(clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
349
cp = (fat_cluster_t *)b->data +
350
clst % (BPS(bs) / sizeof(fat_cluster_t));
351
*cp = host2uint16_t_le(value);
352
b->dirty = true; /* need to sync block */
285
* @param service_id Service ID for the file system.
286
* @param clst Cluster which to get.
287
* @param value Output argument holding the value of the cluster.
289
* @return EOK or a negative error code.
292
fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
293
fat_cluster_t clst, fat_cluster_t *value)
296
uint16_t byte1, byte2;
300
offset = (clst + clst / 2);
301
if (offset / BPS(bs) >= SF(bs))
304
rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
305
offset / BPS(bs), BLOCK_FLAGS_NONE);
309
byte1 = ((uint8_t *) b->data)[offset % BPS(bs)];
310
/* This cluster access spans a sector boundary. Check only for FAT12 */
311
if ((offset % BPS(bs)) + 1 == BPS(bs)) {
312
/* Is this the last sector of FAT? */
313
if (offset / BPS(bs) < SF(bs)) {
314
/* No, read the next sector */
315
rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
316
SF(bs) * fatno + offset / BPS(bs),
323
* Combining value with last byte of current sector and
324
* first byte of next sector
326
byte2 = ((uint8_t*) b1->data)[0];
334
/* Yes. This is the last sector of FAT */
339
byte2 = ((uint8_t *) b->data)[(offset % BPS(bs)) + 1];
341
*value = uint16_t_le2host(byte1 | (byte2 << 8));
343
*value = (*value) >> 4;
345
*value = (*value) & FAT12_MASK;
352
/** Get cluster from the first FAT.
354
* @param bs Buffer holding the boot sector for the file system.
355
* @param service_id Service ID for the file system.
356
* @param clst Cluster which to get.
357
* @param value Output argument holding the value of the cluster.
359
* @return EOK or a negative error code.
362
fat_get_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
363
fat_cluster_t clst, fat_cluster_t *value)
369
offset = (clst * FAT16_CLST_SIZE);
371
rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
372
offset / BPS(bs), BLOCK_FLAGS_NONE);
376
*value = uint16_t_le2host(*(uint16_t *)(b->data + offset % BPS(bs)));
383
/** Get cluster from the first FAT.
385
* @param bs Buffer holding the boot sector for the file system.
386
* @param service_id Service ID for the file system.
387
* @param clst Cluster which to get.
388
* @param value Output argument holding the value of the cluster.
390
* @return EOK or a negative error code.
393
fat_get_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
394
fat_cluster_t clst, fat_cluster_t *value)
400
offset = (clst * FAT32_CLST_SIZE);
402
rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
403
offset / BPS(bs), BLOCK_FLAGS_NONE);
407
*value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))) &
416
/** Get cluster from the first FAT.
418
* @param bs Buffer holding the boot sector for the file system.
419
* @param service_id Service ID for the file system.
420
* @param clst Cluster which to get.
421
* @param value Output argument holding the value of the cluster.
423
* @return EOK or a negative error code.
426
fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
427
fat_cluster_t clst, fat_cluster_t *value)
431
assert(fatno < FATCNT(bs));
433
if (FAT_IS_FAT12(bs))
434
rc = fat_get_cluster_fat12(bs, service_id, fatno, clst, value);
435
else if (FAT_IS_FAT16(bs))
436
rc = fat_get_cluster_fat16(bs, service_id, fatno, clst, value);
438
rc = fat_get_cluster_fat32(bs, service_id, fatno, clst, value);
443
/** Set cluster in one instance of FAT.
445
* @param bs Buffer holding the boot sector for the file system.
446
* @param service_id Service ID for the file system.
447
* @param fatno Number of the FAT instance where to make the change.
448
* @param clst Cluster which is to be set.
449
* @param value Value to set the cluster with.
451
* @return EOK on success or a negative error code.
454
fat_set_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
455
fat_cluster_t clst, fat_cluster_t value)
457
block_t *b, *b1 = NULL;
459
uint16_t byte1, byte2;
462
offset = (clst + clst / 2);
463
if (offset / BPS(bs) >= SF(bs))
466
rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
467
offset / BPS(bs), BLOCK_FLAGS_NONE);
471
byte1 = ((uint8_t*) b->data)[offset % BPS(bs)];
473
/* This cluster access spans a sector boundary. */
474
if ((offset % BPS(bs)) + 1 == BPS(bs)) {
475
/* Is it the last sector of FAT? */
476
if (offset / BPS(bs) < SF(bs)) {
477
/* No, read the next sector */
478
rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
479
SF(bs) * fatno + offset / BPS(bs),
486
* Combining value with last byte of current sector and
487
* first byte of next sector
489
byte2 = ((uint8_t *) b1->data)[0];
492
/* Yes. This is the last sector of FAT */
497
byte2 = ((uint8_t*) b->data)[(offset % BPS(bs)) + 1];
502
value = (value << 4);
509
byte1 = byte1 | (value & 0xff);
510
byte2 = byte2 | (value >> 8);
512
((uint8_t *) b->data)[(offset % BPS(bs))] = byte1;
514
((uint8_t *) b1->data)[0] = byte2;
523
((uint8_t *) b->data)[(offset % BPS(bs)) + 1] = byte2;
525
b->dirty = true; /* need to sync block */
531
/** Set cluster in one instance of FAT.
533
* @param bs Buffer holding the boot sector for the file system.
534
* @param service_id Service ID for the file system.
535
* @param fatno Number of the FAT instance where to make the change.
536
* @param clst Cluster which is to be set.
537
* @param value Value to set the cluster with.
539
* @return EOK on success or a negative error code.
542
fat_set_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
543
fat_cluster_t clst, fat_cluster_t value)
549
offset = (clst * FAT16_CLST_SIZE);
551
rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
552
offset / BPS(bs), BLOCK_FLAGS_NONE);
556
*(uint16_t *)(b->data + offset % BPS(bs)) = host2uint16_t_le(value);
558
b->dirty = true; /* need to sync block */
564
/** Set cluster in one instance of FAT.
566
* @param bs Buffer holding the boot sector for the file system.
567
* @param service_id Service ID for the file system.
568
* @param fatno Number of the FAT instance where to make the change.
569
* @param clst Cluster which is to be set.
570
* @param value Value to set the cluster with.
572
* @return EOK on success or a negative error code.
575
fat_set_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
576
fat_cluster_t clst, fat_cluster_t value)
583
offset = (clst * FAT32_CLST_SIZE);
585
rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
586
offset / BPS(bs), BLOCK_FLAGS_NONE);
590
temp = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs)));
592
temp |= (value & FAT32_MASK);
593
*(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(temp);
595
b->dirty = true; /* need to sync block */
601
/** Set cluster in one instance of FAT.
603
* @param bs Buffer holding the boot sector for the file system.
604
* @param service_id Device service ID for the file system.
605
* @param fatno Number of the FAT instance where to make the change.
606
* @param clst Cluster which is to be set.
607
* @param value Value to set the cluster with.
609
* @return EOK on success or a negative error code.
612
fat_set_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
613
fat_cluster_t clst, fat_cluster_t value)
617
assert(fatno < FATCNT(bs));
619
if (FAT_IS_FAT12(bs))
620
rc = fat_set_cluster_fat12(bs, service_id, fatno, clst, value);
621
else if (FAT_IS_FAT16(bs))
622
rc = fat_set_cluster_fat16(bs, service_id, fatno, clst, value);
624
rc = fat_set_cluster_fat32(bs, service_id, fatno, clst, value);
357
629
/** Replay the allocatoin of clusters in all shadow instances of FAT.
359
631
* @param bs Buffer holding the boot sector of the file system.
360
* @param devmap_handle Device handle of the file system.
632
* @param service_id Service ID of the file system.
361
633
* @param lifo Chain of allocated clusters.
362
634
* @param nclsts Number of clusters in the lifo chain.
364
636
* @return EOK on success or a negative error code.
366
int fat_alloc_shadow_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle,
638
int fat_alloc_shadow_clusters(fat_bs_t *bs, service_id_t service_id,
367
639
fat_cluster_t *lifo, unsigned nclsts)
643
fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
373
for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
646
for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) {
374
647
for (c = 0; c < nclsts; c++) {
375
rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],
376
c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
648
rc = fat_set_cluster(bs, service_id, fatno, lifo[c],
649
c == 0 ? clst_last1 : lifo[c - 1]);
417
689
* Search FAT1 for unused clusters.
419
691
fibril_mutex_lock(&fat_alloc_lock);
420
for (b = 0, cl = 0; b < SF(bs); b++) {
421
rc = block_get(&blk, devmap_handle, RSCNT(bs) + b,
692
for (clst = FAT_CLST_FIRST; clst < CC(bs) + 2 && found < nclsts;
694
rc = fat_get_cluster(bs, service_id, FAT1, clst, &value);
425
for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) {
698
if (value == FAT_CLST_RES0) {
427
* Check if the entire cluster is physically there.
428
* This check becomes necessary when the file system is
429
* created with fewer total sectors than how many is
430
* inferred from the size of the file allocation table
431
* or when the last cluster ends beyond the end of the
700
* The cluster is free. Put it into our stack
701
* of found clusters and mark it as non-free.
434
if ((cl >= FAT_CLST_FIRST) &&
435
CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) {
704
rc = fat_set_cluster(bs, service_id, FAT1, clst,
705
(found == 0) ? clst_last1 : lifo[found - 1]);
442
fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
443
if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
445
* The cluster is free. Put it into our stack
446
* of found clusters and mark it as non-free.
449
*clst = (found == 0) ?
450
host2uint16_t_le(FAT_CLST_LAST1) :
451
host2uint16_t_le(lifo[found - 1]);
452
blk->dirty = true; /* need to sync block */
453
if (++found == nclsts) {
454
/* we are almost done */
458
/* update the shadow copies of FAT */
459
rc = fat_alloc_shadow_clusters(bs,
460
devmap_handle, lifo, nclsts);
463
*mcl = lifo[found - 1];
466
fibril_mutex_unlock(&fat_alloc_lock);
713
if (rc == EOK && found == nclsts) {
714
rc = fat_alloc_shadow_clusters(bs, service_id, lifo, nclsts);
716
*mcl = lifo[found - 1];
474
719
fibril_mutex_unlock(&fat_alloc_lock);
480
fibril_mutex_unlock(&fat_alloc_lock);
483
* We could not find enough clusters. Now we need to free the clusters
484
* we have allocated so far.
724
/* If something wrong - free the clusters */
486
725
while (found--) {
487
rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
726
(void) fat_set_cluster(bs, service_id, FAT1, lifo[found],
731
fibril_mutex_unlock(&fat_alloc_lock);
499
736
/** Free clusters forming a cluster chain in all copies of FAT.
501
738
* @param bs Buffer hodling the boot sector of the file system.
502
* @param devmap_handle Device handle of the file system.
739
* @param service_id Device service ID of the file system.
503
740
* @param firstc First cluster in the chain which is to be freed.
505
742
* @return EOK on success or a negative return code.
508
fat_free_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc)
745
fat_free_clusters(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc)
748
fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs);
514
751
/* Mark all clusters in the chain as free in all copies of FAT. */
515
while (firstc < FAT_CLST_LAST1) {
516
assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
517
rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc);
752
while (firstc < FAT_CLST_LAST1(bs)) {
753
assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);
755
rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc);
520
for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
521
rc = fat_set_cluster(bs, devmap_handle, fatno, firstc,
759
for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
760
rc = fat_set_cluster(bs, service_id, fatno, firstc,