⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tffs.c

📁 MMI层OBJ不能完全编译
💻 C
📖 第 1 页 / 共 3 页
字号:
    tw(tr(TR_FUNC, TrPowerfail, "powerfail_test_begin(0x%x, 0x%x, 0x%x) \n", 
          mode, offset, mask));

    memset(&powerfail, 0 ,sizeof(powerfail));
    powerfail.mode   = mode;
    powerfail.offset = offset;
    powerfail.bytemask   = mask;
}

// NOTEME change to macro?
void powerfail_test_end(void)
{
    tw(tr(TR_FUNC, TrPowerfail, "powerfail_test_end() \n"));
    powerfail.mode = 0;
    powerfail.enable = 0;
    // NOTEME: Display stats?
}


// NOTEME change to macro?  
// In the start of the journal code and in other critical places (start of
// each domain), the below function is called. The function enables and
// disables powerfail. It is important that it called before any driver
// write in the current domain.
void powerfail_domain_begin(int domain)
{
    if (powerfail.mode == 0) 
        return;

    tw(tr(TR_FUNC, TrPowerfail, "powerfail_begin_domain(0x%x)\n", domain));

    powerfail.enable = powerfail.mode & domain;
}

// NOTEME change to macro?
// This function is called at the end of each domain.
void powerfail_domain_end(void)
{
    if (powerfail.enable == 0) 
        return;

    tw(tr(TR_FUNC, TrPowerfail, "powerfail_end_domain()\n")); 

    powerfail.enable = 0;
}

int powerfail_suspend_test(void)
{
    int mode = powerfail.mode;
    powerfail.mode = 0;
    powerfail.enable = 0;
    return mode;
}

void powerfail_resume_test(int mode)
{
    powerfail.mode = mode;
}


// The below function sets the absolute address used for powerfail. It is
// important that the function powerfail_set_domain() is called before this
// function as that function determine if the powerfail is enabled or not
// for this domain. Typical 'addr' will be the address of a inode or block
// header.
void powerfail_set_addr(int addr)
{
    if (POWERFAIL_ENABLED) {
        tw(tr(TR_FUNC, TrPowerfail, "powerfail_set_addr(0x%x)\n", addr)); 

        if (powerfail.mode & PFM_RANDOM) 
            return;  // Skip because this test do not use addr

        else if (powerfail.mode & PFM_NEXTINODE) 
            powerfail.addr = powerfail.offset + (int)inode_addr(fs.journal.i);

        else if (powerfail.mode & PFM_DIRI) 
            powerfail.addr = powerfail.offset + (int)inode_addr(fs.journal.diri);

        else if (powerfail.mode & PFM_OLDI) 
            powerfail.addr = powerfail.offset + (int)inode_addr(fs.journal.oldi);

        else if (powerfail.mode & PFM_JOURNAL) {
            struct inode_s *ip = inode_addr(fs.ijournal);
            powerfail.addr = (int)offset2addr(location2offset(ip->location) + 
                                         fs.journal_pos);
        }
        else if (powerfail.mode & PFM_BLOCKHEADER)
            powerfail.addr = powerfail.offset + addr;
        else {
            tw(tr(TR_FUNC, TrAll, "unknown powerfail mode\n"));
            // NOTEME use other error code?
            powerfail_fatal_error(-1);
        }

        // Aligned to halfword?
        if (powerfail.addr & 1) {
            // Not aligned, aligne addr and fix mask
            powerfail.addr--;
            powerfail.halfwordmask = powerfail.bytemask << 8;
        }
        else
            powerfail.halfwordmask = powerfail.bytemask;

        tw(tr(TR_FUNC, TrPowerfail, "pf addr 0x%x, mask 0x%x \n", powerfail.addr, 
              powerfail.halfwordmask)); 
    }
}

// The following function is called conditionally from within the driver's
// write function. The condition gating the call is (powerfail.mode > 0 and
// powerfail.enable > 0).
void powerfail_write(volatile uint16 *addr, uint16 value) 
{
    int mode;
    
   tw(tr(TR_FUNC, TrPowerfail, "powerfail_write(0x%x, 0x%x)\n", addr, value));
  
   if (powerfail.mode & PFM_RANDOM) {
        // Not all these calls trigger a powerfail..
        if ((rand() % powerfail.offset) > 0)
            return;  // Skip powerfail
        powerfail_simulate_random_write_failures(addr, value);
   }
   else if (powerfail.mode & (PFM_INODES | PFM_JOURNAL | PFM_BLOCKHEADER)) {
       // Is this the addr and is the mask bits changed?
       if ((int)addr != powerfail.addr || ((*addr ^ value) & powerfail.halfwordmask) == 0)
           return;  // Skip powerfail 
       powerfail_simulate_write_failures(addr, value); 
   }
   else {
        tw(tr(TR_FUNC, TrAll, "Unknown powerfail_mode\n"));
        // NOTEME use other error code
        powerfail_fatal_error(-2); 
   }

   tmp_fix_trace_indent();

   powerfail.step++;

   if (!(powerfail.mode & PFM_NOINIT)) {
       mode = powerfail_suspend_test(); 

       // Now re-initialise FFS. Then resume at the point we were before.
       // We should ensure that all static variables of ffs are zeroed during
       // re-initialization!  
       tw(tr(TR_FUNC, TrPowerfail,"re-initialise FFS (step %d)\n", powerfail.step));
       memset(&fs, 0, sizeof(struct fs_s));
       ffs_initialize();

       powerfail_resume_test(mode);
   }

   tw(tr(TR_FUNC, TrPowerfail, "jump..\n")); 
   longjmp(powerfail.env, 0);
}


// This function is used to simulate the Intel Strata Flash. It only
// corrupts the cells that are modified by the write and it only corrupts
// the cells in the way it can happen in a real device e.g. if the existing
// cell level is 0 (11b) and a write of level 2 (01b) is corrupted, the
// function will "corrupt" the cell by setting the state to either 0, 1 or 2
// and not to 3 (00b) as this is not how the Strata flash work.
int powerfail_simulate_random_write_failures(volatile uint16 *addr, uint16 src)
{
    int i;
    uint16 out_cell, flash_cell, src_cell;
    uint16 mask, out;
    uint16 diff;

    out = *addr;

    tw(tr(TR_FUNC, TrPowerfail, "pf_sim_random_wr_fail(0x%x, 0x%x)\n", 
          addr, src));
 
    tw(tr(TR_FUNC, TrTest, 
          "POWER FAIL AT ADDR: 0x%x. Before 0x%x\n"
          "\t\t\t\t  Wanted 0x%x\n", addr, *addr, src));

    if (~*addr & src) {
        ffsdrv_write_error(*addr, src);
        // NOTEME use other error code?
        powerfail_fatal_error(-3);
    }

    // Isolate and corrupt cell per cell 
    for (i = 0; i < 16; i++) {
        // Move flash and src down to lowest 'cell' 
        flash_cell = *addr >> (i * 2);
        src_cell   = src   >> (i * 2);
        // Maskout all bits except from the 2 lowest bits
        flash_cell &=  0x03;  
        src_cell   &= 0x03;

        diff = flash_cell - src_cell;

        if (diff == 0)
            continue;  // Skip, not possible to corrupt the cell

        out_cell = flash_cell - (rand() % (diff + 1));

        if (out_cell < src_cell) {
            tw(tr(TR_NULL, TrTest,"Bad out_cell, src 0x%x, out 0x%x\n", 
                  src_cell, out_cell));
            // NOTEME use other error code?
            powerfail_fatal_error(-4);
        }

        // Move the cell back to the original place 
        out_cell = out_cell << (i * 2);

        // Set all bits except from the current cell
        mask = 0x3 << (i * 2); 
        out_cell |= ~mask;

        // Added the result to the output data
        out = out_cell & out;
    }

    tw(tr(TR_NULL, TrTest,"\t\t\t\t  Result 0x%x\n", out));

    if (~*addr & out) {
        ffsdrv_write_error(*addr, out);
        // NOTEME use other error code?
        powerfail_fatal_error(-5);
    }

    *addr = out;

    return EFFS_OK;
}

// Simulate write failures if the powerfail.mask bits are changed by src. If
// the mask bits are modified by src, 'write' the mask bits and return 0. If
// the mask bits not are valid, trace and return an error. The mask bits are
// invalid if the mask 'cell' level is higher than src.
int powerfail_simulate_write_failures(volatile uint16 *addr, uint16 src)
{
    int i;
    uint16 out_cell, flash_cell, src_cell, mask_cell;
    uint16 out;
    
    out = *addr;

    tw(tr(TR_FUNC, TrPowerfail, "pf_sim_wr_fail(0x%x, 0x%x)\n", addr, src));
 
    tw(tr(TR_FUNC, TrTest, "POWER FAIL AT ADDR: 0x%x. Before 0x%x\n"
          "\t\t\t\t  Wanted 0x%x\n", addr, *addr, src));

    // Isolate and corrupt cell per cell 
    for (i = 0; i < 16; i++) {
        // Move flash and src down to lowest 'cell' 
        flash_cell = *addr >> (i * 2);
        src_cell   = src   >> (i * 2);
        mask_cell  = ~(powerfail.halfwordmask  >> (i * 2));
        // Maskout all bits except from the 2 lowest bits
        flash_cell &=  0x03;  
        src_cell   &= 0x03;
        mask_cell   &= 0x03;

        // The cell have changed and is marked by mask so check if the mask
        // is valid. e.g. a write of '10b' cannot be set to '00b' by mask
        if (mask_cell < src_cell) {
            tw(tr(TR_FUNC, TrAll, "FATAL invalid mask: 0x%x\n", powerfail.halfwordmask));
            // NOTEME use other error code?
            powerfail_fatal_error(-6);
        }

        // Would the cell have been changed by src and is it marked by mask?
        if ((flash_cell == src_cell) || (mask_cell == 3))
            continue;  // Skip, the cell will not be changed by src or the
                       // cell is not marked by mask

        // Move the cell back to the original place 
        out_cell = mask_cell << (i * 2);

        // Set all bits except from the current cell
        out_cell |= ~(0x3 << (i * 2)); 

        // Added the result to the output data
        out &= out_cell;
    }

    tw(tr(TR_NULL, TrTest,"\t\t\t\t  Result 0x%x\n", out));
    *addr = out;

    return EFFS_OK;
}

// PFM_ERASE: makes powerfail while erasing the block specified in pf
// variable 'offset'. Instead of erasing the flash it is filled with the
// pattern applied by the pf 'bytemask' (e.g. 0xFF, 0x0, 0xAA etc).

// PFM_NEXTERASE: makes powerfail at the next block erase. The 'bytemask 'is
// used to fill the block.

// PFM_RANDOM: the 'offset' value determine how often it triggers a
// powerfail. Difference patterns are used to fill the block */
void powerfail_erase(uint8 block)
{
    int i, mode;
    uint8 *addr;

    tw(tr(TR_FUNC, TrPowerfail, "powerfail_erase(%d)\n", block));

    if (powerfail.mode & PFM_RANDOM) {
        if ((rand() % powerfail.offset) > 0)
            return;  // Skip powerfail
        
        powerfail.bytemask = rand() % 0xFF;
    }
    else if (powerfail.mode & PFM_ERASE) {
        if (powerfail.offset != block)
            return; // Skip powerfail
    }
    else if (powerfail.mode & PFM_NEXTERASE) {
        // offset is not used, bytemask is set in powerfail_test_begin() 
    }

    tw(tr(TR_FUNC, TrTest, "POWER FAIL AT BLOCK ERASE: %d \n", block));

    // Fill the block with the bytemask
    addr = block2addr(block);
    for (i = 0; i < 1 << dev.binfo[block].size_ld; i++) {
        *addr++ = powerfail.bytemask;
    }

    powerfail.step++;
    
    if (!(powerfail.mode & PFM_NOINIT)) {
        mode = powerfail_suspend_test(); 

        // Now re-initialise FFS. Then resume at the point we were before.
        // We should ensure that all static variables of ffs are zeroed during
        // re-initialization!  
        tw(tr(TR_FUNC, TrPowerfail,"re-initialise FFS (step %d)\n", powerfail.step));
        memset(&fs, 0, sizeof(struct fs_s));
        ffs_initialize();

        powerfail_resume_test(mode);
    }

    tw(tr(TR_FUNC, TrPowerfail, "jump..\n")); 
    longjmp(powerfail.env, 0);

}

void powerfail_fatal_error(int error)
{
    tw(tr(TR_FUNC, TrAll, "FATAL pf error %d\n", error));
    ttw(ttr(TTrFatal, "FATAL pf error %d" NL, error));

    powerfail_display_stats();

    exit(1);
}

void powerfail_display_stats(void)
{
    tw(tr(TR_FUNC, TrTest, "powerfail: \n"));
    tw(tr(TR_FUNC, TrTest, " mode:     0x%x\n", powerfail.mode));
    tw(tr(TR_FUNC, TrTest, " boundary: 0x%x\n", powerfail.boundary));
    tw(tr(TR_FUNC, TrTest, " step:     0x%x\n", powerfail.step));

    ttw(ttr(TTrAll, "powerfail:" NL));
    ttw(ttr(TTrAll, "mode:     0x%x" NL, powerfail.mode));
    ttw(ttr(TTrAll, "boundary: 0x%x" NL, powerfail.boundary));
    ttw(ttr(TTrAll, "step:     0x%x" NL, powerfail.step));
}

void tmp_fix_trace_indent(void)
{
    if (powerfail.boundary == JOURNAL_TEST_COMMITTING)
        tw(tr(TR_END, TrJournal, "} dummy \n"));

    if (powerfail.boundary == JOURNAL_TEST_READY)
        tw(tr(TR_END, TrJournal, "} dummy \n"));


    tw(tr(TR_END, TrJournal, "} dummy \n"));
}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -