Пример #1
0
/**
 * \brief Unlock all the regions in the given address range. The actual unlock
 * range is reported through two output parameters.
 *
 * \param ul_start Start address of unlock range.
 * \param ul_end End address of unlock range.
 * \param pul_actual_start Start address of the actual unlock range (optional).
 * \param pul_actual_end End address of the actual unlock range (optional).
 *
 * \return 0 if successful, otherwise returns an error code.
 */
uint32_t flash_unlock(uint32_t ul_start, uint32_t ul_end,
		uint32_t *pul_actual_start, uint32_t *pul_actual_end)
{
	Efc *p_efc;
	uint32_t ul_actual_start, ul_actual_end;
	uint16_t us_start_page, us_end_page;
	uint32_t ul_error;
	uint16_t us_num_pages_in_region =
			IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;

	/* Compute actual unlock range and store it */
	compute_lock_range(ul_start, ul_end, &ul_actual_start, &ul_actual_end);
	if (pul_actual_start != NULL) {
		*pul_actual_start = ul_actual_start;
	}
	if (pul_actual_end != NULL) {
		*pul_actual_end = ul_actual_end;
	}

	/* Compute page numbers */
	translate_address(&p_efc, ul_actual_start, &us_start_page, 0);
	translate_address(0, ul_actual_end, &us_end_page, 0);

	/* Unlock all pages */
	while (us_start_page < us_end_page) {
		ul_error = efc_perform_command(p_efc, EFC_FCMD_CLB,
				us_start_page);
		if (ul_error) {
			return ul_error;
		}
		us_start_page += us_num_pages_in_region;
	}

	return FLASH_RC_OK;
}
Пример #2
0
/**
 * \brief Get the number of locked regions inside the given address range.
 *
 * \param ul_start Start address of range
 * \param ul_end End address of range.
 *
 * \return The number of locked regions inside the given address range.
 */
uint32_t flash_is_locked(uint32_t ul_start, uint32_t ul_end)
{
	Efc *p_efc;
	uint16_t us_start_page, us_end_page;
	uint8_t uc_start_region, uc_end_region;
	uint16_t us_num_pages_in_region;
	uint32_t ul_status;
	uint32_t ul_error;
	uint32_t ul_num_locked_regions = 0;
	uint32_t ul_count = 0;
	uint32_t ul_bit = 0;

	/* Compute page numbers */
	translate_address(&p_efc, ul_start, &us_start_page, 0);
	translate_address(0, ul_end, &us_end_page, 0);

	/* Compute region numbers */
	us_num_pages_in_region = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
	uc_start_region = us_start_page / us_num_pages_in_region;
	uc_end_region = us_end_page / us_num_pages_in_region;

	/* Retrieve lock status */
	ul_error = efc_perform_command(p_efc, EFC_FCMD_GLB, 0);

	/* Skip unrequested regions (if necessary) */
	ul_status = efc_get_result(p_efc);
	while (!(ul_count <= uc_start_region &&
			uc_start_region < (ul_count + 32))) {
		ul_status = efc_get_result(p_efc);
		ul_count += 32;
	}

	/* Check status of each involved region */
	ul_bit = uc_start_region - ul_count;

	/* Number of region to check (must be > 0) */
	ul_count = uc_end_region - uc_start_region + 1;

	while (ul_count > 0) {
		if (ul_status & (1 << (ul_bit))) {
			ul_num_locked_regions++;
		}

		ul_count -= 1;
		ul_bit += 1;
		if (ul_bit == 32) {
			ul_status = efc_get_result(p_efc);
			ul_bit = 0;
		}
	}

	return ul_num_locked_regions;
}
Пример #3
0
/**
 * \brief Get flash descriptor.
 *
 * \param ul_address Flash bank start address.
 * \param pul_flash_descriptor Pointer to a data buffer to store flash descriptor.
 * \param ul_size Data buffer size in DWORD.
 *
 * \return The actual descriptor length.
 */
uint32_t flash_get_descriptor(uint32_t ul_address,
		uint32_t *pul_flash_descriptor, uint32_t ul_size)
{
	Efc *p_efc;
	uint32_t ul_tmp;
	uint32_t ul_cnt;

	translate_address(&p_efc, ul_address, NULL, NULL);

	/* Command fails */
	if (FLASH_RC_OK != efc_perform_command(p_efc, EFC_FCMD_GETD, 0)) {
		return 0;
	} else {
		/* Read until no result */
		for (ul_cnt = 0;; ul_cnt++) {
			ul_tmp = efc_get_result(p_efc);
			if ((ul_size > ul_cnt) && (ul_tmp != 0)) {
				*pul_flash_descriptor++ = ul_tmp;
			} else {
				break;
			}
		}
	}

	return ul_cnt;
}
Пример #4
0
/**
 * \brief Get flash wait state.
 *
 * \param ul_address Flash bank start address.
 *
 * \return The number of wait states in cycle (no shift).
 */
uint32_t flash_get_wait_state(uint32_t ul_address)
{
	Efc *p_efc;

	translate_address(&p_efc, ul_address, NULL, NULL);
	return efc_get_wait_state(p_efc);
}
Пример #5
0
/**
 * \brief Set flash wait state.
 *
 * \param ul_address Flash bank start address.
 * \param ul_fws The number of wait states in cycle (no shift).
 *
 * \return 0 if successful; otherwise returns an error code.
 */
uint32_t flash_set_wait_state(uint32_t ul_address, uint32_t ul_fws)
{
	Efc *p_efc;

	translate_address(&p_efc, ul_address, NULL, NULL);
	efc_set_wait_state(p_efc, ul_fws);

	return FLASH_RC_OK;
}
Пример #6
0
uintptr_t mcall_query_memory(uintptr_t id, memory_block_info *p)
{
	uintptr_t physicalAddr = translate_address((uintptr_t) p);
	memory_block_info *info = (memory_block_info*) physicalAddr;
	if (id == 0) {
		info->base = 0x1000000; // hard coded for now, but we can put these values somewhere later
		info->size = 0x7F000000 - info->base;
		return 0;
	}

	return -1;
}
Пример #7
0
/**
 * \brief Erase the entire flash.
 *
 * \note Only the flash bank including ul_address will be erased. If there are
 * two flash banks, we need to call this function twice with each bank start
 * address.
 *
 * \param ul_address  Flash bank start address.
 *
 * \return 0 if successful; otherwise returns an error code.
 */
uint32_t flash_erase_all(uint32_t ul_address)
{
	Efc *p_efc;

	translate_address(&p_efc, ul_address, NULL, NULL);

	if (EFC_RC_OK != efc_perform_command(p_efc, EFC_FCMD_EA, 0)) {
		return FLASH_RC_ERROR;
	}

	return FLASH_RC_OK;
}
Пример #8
0
/**
 * \brief Erase the flash sector.
 *
 * \note Erase sector command needs a page number parameter which belongs to
 * the sector to be erased.
 *
 * \param ul_address Flash sector start address.
 *
 * \return 0 if successful; otherwise returns an error code.
 */
uint32_t flash_erase_sector(uint32_t ul_address)
{
	Efc *p_efc;
	uint16_t us_page;

	translate_address(&p_efc, ul_address, &us_page, NULL);

	if (EFC_RC_OK != efc_perform_command(p_efc, EFC_FCMD_ES, us_page)) {
		return FLASH_RC_ERROR;
	}

	return FLASH_RC_OK;
}
Пример #9
0
static page * get_page_wrapper(unsigned a, unsigned *offset)
{
    if (!globals.active)
    {
        errno = ENOPROTOOPT;
        return NULL;
    }
    unsigned page_num;
    if (translate_address(a, &page_num, offset) == ERROR)
    {
        errno = EFAULT;
        return NULL;
    }
	if (update_act_queries(INC) == ERROR) return NULL;
    callback_wrapper(1, page_num, 0);
    return get_page(page_num);
}
Пример #10
0
/**
 * \brief Set flash wait state.
 *
 * \param ul_address Flash bank start address.
 * \param ul_fws The number of wait states in cycle (no shift).
 *
 * \return 0 if successful; otherwise returns an error code.
 */
uint32_t flash_set_wait_state_adaptively(uint32_t ul_address)
{
	Efc *p_efc;
	uint32_t clock = SystemCoreClock;

	translate_address(&p_efc, ul_address, NULL, NULL);

	/* Set FWS for embedded Flash access according to operating frequency */
	if (clock < CHIP_FREQ_FWS_0) {
		efc_set_wait_state(p_efc, 0);
	} else if (clock < CHIP_FREQ_FWS_1) {
		efc_set_wait_state(p_efc, 1);
	} else if (clock < CHIP_FREQ_FWS_2) {
		efc_set_wait_state(p_efc, 2);
	} else if (clock < CHIP_FREQ_FWS_3) {
		efc_set_wait_state(p_efc, 3);
	} else {
		efc_set_wait_state(p_efc, 4);
	}
	return FLASH_RC_OK;
}
Пример #11
0
/**
 * \brief Erase the specified pages of flash.
 *
 * \param ul_address Flash bank start address.
 *
 * \return 0 if successful; otherwise returns an error code.
 */
uint32_t flash_erase_page(uint32_t ul_address, uint8_t uc_page_num)
{
	Efc *p_efc;
	uint16_t us_page;

	if (uc_page_num >= IFLASH_ERASE_PAGES_INVALID) {
		return FLASH_RC_INVALID;
	}

	if (ul_address & (IFLASH_PAGE_SIZE - 1)) {
		return FLASH_RC_INVALID;
	}

	translate_address(&p_efc, ul_address, &us_page, NULL);

	if (EFC_RC_OK != efc_perform_command(p_efc, EFC_FCMD_EPA,
					(us_page | uc_page_num))) {
		return FLASH_RC_ERROR;
	}

	return FLASH_RC_OK;
}
Пример #12
0
/**
 * \brief Set flash wait state.
 *
 * \param ul_address Flash bank start address.
 * \param ul_fws The number of wait states in cycle (no shift).
 *
 * \return 0 if successful; otherwise returns an error code.
 */
uint32_t flash_set_wait_state_adaptively(uint32_t ul_address)
{
	Efc *p_efc;
	uint32_t clock = sysclk_get_cpu_hz();

	translate_address(&p_efc, ul_address, NULL, NULL);

	/* Set FWS for embedded Flash access according to operating frequency */
	if (clock < CHIP_FREQ_FWS_0) {
		efc_set_wait_state(p_efc, 0);
	} else if (clock < CHIP_FREQ_FWS_1) {
		efc_set_wait_state(p_efc, 1);
	} else if (clock < CHIP_FREQ_FWS_2) {
		efc_set_wait_state(p_efc, 2);
#if (SAM3XA || SAM3U)
	} else if (clock < CHIP_FREQ_FWS_3) {
		efc_set_wait_state(p_efc, 3);
	} else {
		efc_set_wait_state(p_efc, 4);
	}
#elif (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CP || SAM4CM)
	} else if (clock < CHIP_FREQ_FWS_3) {
Пример #13
0
/* pointer into a kernel-virtual-address pointer in physical space...  */
static dinode_t *make_dinode (u_int uva)
{
   dinode_t *dinode = (dinode_t *) translate_address (uva, CFFS_DINODE_SIZE);
   assert ((dinode == NULL) || ((((u_int) dinode) % NBPG) == (uva % NBPG)));
   return (dinode);
}
Пример #14
0
/**
 * \brief Write a data buffer on flash.
 *
 * \note This function works in polling mode, and thus only returns when the
 * data has been effectively written.
 * \note For dual bank flash, this function doesn't support cross write from
 * bank 0 to bank 1. In this case, flash_write must be called twice (ie for
 * each bank).
 *
 * \param ul_address Write address.
 * \param p_buffer Data buffer.
 * \param ul_size Size of data buffer in bytes.
 * \param ul_erase_flag Flag to set if erase first.
 *
 * \return 0 if successful, otherwise returns an error code.
 */
uint32_t flash_write(uint32_t ul_address, const void *p_buffer,
		uint32_t ul_size, uint32_t ul_erase_flag)
{
	Efc *p_efc;
	uint32_t ul_fws_temp;
	uint16_t us_page;
	uint16_t us_offset;
	uint32_t writeSize;
	uint32_t ul_page_addr;
	uint16_t us_padding;
	uint32_t ul_error;
	uint32_t ul_idx;
	uint32_t *p_aligned_dest;
	uint8_t *puc_page_buffer = (uint8_t *) gs_ul_page_buffer;

	translate_address(&p_efc, ul_address, &us_page, &us_offset);

	/* According to the errata, set the wait state value to 6. */
	ul_fws_temp = efc_get_wait_state(p_efc);
	efc_set_wait_state(p_efc, 6);

	/* Write all pages */
	while (ul_size > 0) {
		/* Copy data in temporary buffer to avoid alignment problems. */
		writeSize = Min((uint32_t) IFLASH_PAGE_SIZE - us_offset,
				ul_size);
		compute_address(p_efc, us_page, 0, &ul_page_addr);
		us_padding = IFLASH_PAGE_SIZE - us_offset - writeSize;

		/* Pre-buffer data */
		memcpy(puc_page_buffer, (void *)ul_page_addr, us_offset);

		/* Buffer data */
		memcpy(puc_page_buffer + us_offset, p_buffer, writeSize);

		/* Post-buffer data */
		memcpy(puc_page_buffer + us_offset + writeSize,
				(void *)(ul_page_addr + us_offset + writeSize),
				us_padding);

		/* Write page.
		 * Writing 8-bit and 16-bit data is not allowed and may lead to
		 * unpredictable data corruption.
		 */
		p_aligned_dest = (uint32_t *) ul_page_addr;
		for (ul_idx = 0; ul_idx < (IFLASH_PAGE_SIZE / sizeof(uint32_t));
				++ul_idx) {
			*p_aligned_dest++ = gs_ul_page_buffer[ul_idx];
		}

		if (ul_erase_flag) {
			ul_error = efc_perform_command(p_efc, EFC_FCMD_EWP,
					us_page);
		} else {
			ul_error = efc_perform_command(p_efc, EFC_FCMD_WP,
					us_page);
		}

		if (ul_error) {
			return ul_error;
		}

		/* Progression */
		p_buffer = (void *)((uint32_t) p_buffer + writeSize);
		ul_size -= writeSize;
		us_page++;
		us_offset = 0;
	}

	/* According to the errata, restore the wait state value. */
	efc_set_wait_state(p_efc, ul_fws_temp);

	return FLASH_RC_OK;
}
Пример #15
0
 void* operator()(void* p) const
 { return translate_address(p); }
Пример #16
0
// CLASS METHOD: Interpreter::exec_load_store_instr()
// PURPOSE:      Load/store instructions move data between memory and the
//               general registers.  They are all encoded as "I-Type"
//               instructions, and the only addressing mode implemented is base
//               register plus signed, immediate offset.  This directly enables
//               the use of three distinct addressing modes: register plus
//               offset; register direct; and immediate.
//
// ARGUMENTS: None.
// RETURNS:   None.
void
Interpreter::exec_load_store_instr(void)
{
    Word vaddr, paddr;

    switch (op(curr_instr))
    {
        // LB -- Load Byte
        // 
        // Sign-extend 16-bit `offset` and add to contents of register `base` to
        // form address.  Sign-extend contents of addressed byte and load into
        // `rt`.
        case LB:
            vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr);
            paddr = translate_address(align(vaddr));

            do_load(LOADREG, rt(curr_instr), sign_ext_byte(mem->read(vaddr, paddr), bytepos(vaddr)));
            break;

        // LBU -- Load Byte Unsigned
        //
        // Sign-extend 16-bit `offse` and add to contents of register `base` to
        // form address.  Zero-extend contents of addressed byte and load into
        // `rt`.
        case LBU:
            vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr);
            paddr = translate_address(align(vaddr));

            do_load(LOADREG, rt(curr_instr), zero_ext_byte(mem->read(vaddr, paddr), bytepos(vaddr)));
            break;

        // LH -- Load Halfword
        //
        // Sign-extend 16-bit `offset` and add to contents of register `base` to
        // form address.  Sign-extend contents of addressed byte and load into
        // `rt`.
        case LH:
            vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr);
            paddr = translate_address(align(vaddr));

            do_load(LOADREG, rt(curr_instr), sign_ext_hword(mem->read(vaddr, paddr), hwordpos(vaddr)));
            break;

        // LHU -- Load Halfword Unsigned
        //
        // Sign-extend 16-bit `offset` and add to contents of register `base` to
        // form address.  Zero-extend contents of addressed byte and load into
        // `rt`.
        case LHU:
            vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr);
            paddr = translate_address(align(vaddr));

            do_load(LOADREG, rt(curr_instr), zero_ext_hword(mem->read(vaddr, paddr), hwordpos(vaddr)));
            break;

        // LW -- Load Word
        //
        // Sign-extend 16-bit `offset` and add to contents of register `base` to
        // form address.  Load contents of addressed word into register `rt`.
        case LW:
            vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr);
            paddr = translate_address(align(vaddr));

            do_load(LOADREG, rt(curr_instr), mem->read(vaddr, paddr));
            break;

        // LWL -- Load Word Left
        //
        // Sign-extend 16-bit `offset` and add to contents of register `base` to
        // form address.  Shift addressed word left so that addressed byte is
        // leftmost byte of a word.  Merge bytes from memory with contents of
        // register `rt` and load result into register `rt`.
        case LWL:
            vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr);
            paddr = translate_address(align(vaddr));

            do_load(LOADREG, rt(curr_instr), merge(gpr[rt(curr_instr)], mem->read(vaddr, paddr), bytepos(vaddr), true));
            break;

        // LWR -- Load Word Right
        //
        // Sign-extend 16-bit `offset` and add to contents of register `base` to
        // form address.  Shfit addressed word right so that addressed byte is
        // rightmost byte of a word.  Merge bytes from memory with contents of
        // register `rt` and load result into register `rt`.
        case LWR:
            vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr);
            paddr = translate_address(align(vaddr));

            do_load(LOADREG, rt(curr_instr), merge(gpr[rt(curr_instr)], mem->read(vaddr, paddr), bytepos(vaddr), false));
            break;

        // SB -- Store Byte
        //
        // Sign-extend 16-bit `offset` and add to contents of register `base` to
        // form address.  Store least significant byte of register `rt` at
        // addressed location.
    }
}
Пример #17
0
// int cffsd_fsupdate_dinode (u_int sn, int action, struct dinode *d, u_int param1, u_int param2, u_int param3)
int serv_fsupdate_dinode (u_int client_eid, int action, struct cffsd_fsupdate_dinode_arg *arg)
{
    int i;
    char *indirblock;
    struct dinode *d;
    u_int param1 = arg->param1;
    u_int param2 = arg->param2;
    u_int param3 = arg->param3;

    dinode_t *dinode;

    debug_request = 1;

    dinode = d  = translate_address (&arg->dinode);

    if (dinode == NULL) {
        kprintf ("sys_fsupdate_dinode: bad address supplied\n");
        return (-E_INVAL);
    }

    StaticAssert (sizeof(dinode_t) == CFFS_DINODE_SIZE);
    /*
       printf ("sys_fsupdate_dinode: action %d, param1 %d (%x), param2 %d\n", action, param1, param1, (u_int)param2);
       printf ("dinodeNum %d\n", dinode->dinodeNum);
    */

    switch (action) {
    case CFFS_DINODE_SETMASK:
        cffs_dinode_setMask (dinode, (mode_t)param1);
        break;
    case CFFS_DINODE_SETUID:
        cffs_dinode_setUid (dinode, (uid_t)param1);
        break;
    case CFFS_DINODE_SETGID:
        cffs_dinode_setGid (dinode, (gid_t)param1);
        break;
    case CFFS_DINODE_SETACCTIME:
        cffs_dinode_setAccTime (dinode, param1);
        break;
    case CFFS_DINODE_SETMODTIME:
        cffs_dinode_setModTime (dinode, param1);
        break;
    case CFFS_DINODE_SETCRETIME:
        cffs_dinode_setCreTime (dinode, param1);
        break;
    case CFFS_DINODE_SETLENGTH:
        cffs_dinode_setLength (dinode, param2);
        assert (dinode->length == param2);
        break;

    case CFFS_DINODE_SETTYPE:
        if (dinode->type == param1) {
            return (0);
        }
        if ((dinode->dinodeNum != 0) && ((cffs_dinode_isDir(dinode)) || (param1 == S_IFDIR))) {
            printf ("sys_fsupdate_dinode (%d): trying to change type to or from directory (%d -> %d)\n", action, dinode->type, param1);
            return (-E_INVAL);
        }
        cffs_dinode_setType (dinode, (u_int16_t)param1);
        break;

    case CFFS_DINODE_SETLINKCOUNT:
        if ((dinode->dinodeNum != 0) && (dinode->linkCount != param1)) {
            printf ("sys_fsupdate_dinode (%d): changing link count directly (%d -> %d)\n", action, dinode->linkCount, param1);
            //return (-E_INVAL);
        }
        cffs_dinode_setLinkCount (dinode, (nlink_t)param1);
        break;

    case CFFS_DINODE_SETOPENCOUNT:
        cffs_dinode_setOpenCount (dinode, param1);
        break;

    case CFFS_DINODE_SETDIRNUM:
        if (cffs_dinode_isDir(dinode)) {
            printf ("sys_fsupdate_dinode (%d): trying to change dirNum of directory directly (%d -> %d) requested\n", action, dinode->dirNum, param1);
            return (-E_INVAL);
        }
        cffs_dinode_setDirNum (dinode, param1);
        break;

    case CFFS_DINODE_SETDIRECT:
        cffs_dinode_setDirect (dinode, param1, (u_int)param2);
        break;

    case CFFS_DINODE_SETINDIRECT:
        cffs_dinode_setIndirect (dinode, param1, (u_int)param2);
        break;

    case CFFS_DINODE_SETGROUPSTART:
        cffs_dinode_setGroupstart (dinode, param1);
        break;
    case CFFS_DINODE_SETGROUPSIZE:
        cffs_dinode_setGroupsize (dinode, param1);
        break;
    case CFFS_DINODE_CLEARBLOCKPOINTERS:
        cffs_dinode_clearBlockPointers(dinode, param2);
        break;

    case CFFS_DINODE_DELAYEDFREE:
        if ((dinode->linkCount > (cffs_dinode_isDir(dinode))) || (dinode->openCount != 0)) {
            printf ("sys_fsupdate_dinode (%d): can't free dinode with links or opens (%d, %d) requested\n", action, dinode->linkCount, dinode->openCount);
            return (-E_INVAL);
        }
        for (i=0; i<NUM_DIRECT; i++) {
            if (dinode->directBlocks[i] != 0) {
                printf ("sys_fsupdate_dinode (%d): can't free dinode with direct blocks (%d == %d) requested\n", action, i, dinode->directBlocks[i]);
                return (-E_INVAL);
            }
        }
        for (i=0; i<NUM_INDIRECT; i++) {
            if (dinode->indirectBlocks[i] != 0) {
                printf ("sys_fsupdate_dinode (%d): can't free dinode with indirect blocks (%d == %d) requested\n", action, i, dinode->indirectBlocks[i]);
                return (-E_INVAL);
            }
        }
        /* In the real system, this wants to occur only after the block is written (unless it is not dirty) */
        dinode->dinodeNum = 0;
        break;

    case CFFS_DINODE_INITINDIRBLOCK:
        indirblock = (char *) dinode;

        /* XXX % */
        if ((indirblock == NULL) || ((u_int)indirblock % BLOCK_SIZE)) {
            printf ("sys_fsupdate_dinode (%d): bad indirblock address supplied (%p)\n", action, indirblock);
            return (-E_INVAL);
        }
        bzero (indirblock, BLOCK_SIZE);
        break;
    case CFFS_DINODE_INITDINODE:
        bzero ((char *)dinode, CFFS_DINODE_SIZE);
        dinode->memory_sanity = CFFS_DINODE_MEMORYSANITY;
        dinode->type = param1;
        dinode->linkCount = (cffs_dinode_isDir(dinode)) ? 2 : 1;
        dinode->dinodeNum = param2;
        dinode->dirNum = param3;
        break;

    default:
        printf ("sys_fsupdate_dinode: unknown action (%d) requested\n", action);
        return (-E_INVAL);
    }

    return (0);
}
Пример #18
0
// int cffsd_fsupdate_directory (u_int sn, int action, struct embdirent *dirent, u_int param2, u_int param3, u_int param4, u_int param5)
int serv_fsupdate_directory (u_int client_eid, int action, struct cffsd_fsupdate_directory_arg *arg)
{
    struct embdirent *dirent;
    u_int param2 = arg->param2;
    u_int param3 = arg->uint_param3;
    //  u_int param4 = arg->uint_param4;
    u_int param5 = arg->param5;

    u_int param1;
    /* XXX % */
    // char *dirBlock = (char *) translate_address ((param1 - (param1 % BLOCK_SIZE)), BLOCK_SIZE);
    char *dirBlock;

    debug_request = 3;

    dirent = translate_address (&arg->dirent);
    param1 = (u_int) dirent;
    dirBlock = (char *)((param1 - (param1 % BLOCK_SIZE)));

    if (dirBlock == NULL) {
        return (-E_INVAL);
    }

    /* XXX % */
    dirent = (embdirent_t *) (dirBlock + (param1 % BLOCK_SIZE));

    /* GROK -- need to check for write permission on directory.  The relevant  */
    /* inode should be provided automatically by base disk protection software */

    if (!isValidDirent(dirBlock, dirent)) {
        printf ("sys_fsupdate_directory (%d): invalid dirent specified (%x)\n", action, param1);
        return (-E_INVAL);
    }

    /************************** CFFS_DIRECTORY_INITDIRBLOCK ***********************/

    if (action == CFFS_DIRECTORY_INITDIRBLOCK) {
        int i;
        dinode_t *dinode;

        /* XXX */
        if ((u_int)dirent % BLOCK_SIZE) {
            printf ("sys_fsupdate_directory (%d): dirent not start of block (%p)\n", action, dirent);
            return (-E_INVAL);
        }

        bzero ((char *)dirent, BLOCK_SIZE);

        for (i=0; i<(BLOCK_SIZE/CFFS_EMBDIR_SECTOR_SIZE); i++) {
            dirent->type = (char) 0;
            dirent->entryLen = CFFS_EMBDIR_SECTOR_SPACEFORNAMES;
            dirent->preventryLen = 0;

            dinode = (dinode_t *) ((char *)dirent + CFFS_DINODE_SIZE);
            dinode->dinodeNum = 0;
            dinode = (dinode_t *) ((char *)dirent + (2*CFFS_DINODE_SIZE));
            dinode->dinodeNum = 0;
            dinode = (dinode_t *) ((char *)dirent + (3*CFFS_DINODE_SIZE));
            dinode->dinodeNum = 0;

            dirent = (embdirent_t *) ((char *) dirent + CFFS_EMBDIR_SECTOR_SIZE);
        }


        /*************************** CFFS_DIRECTORY_SPLITENTRY ************************/

    } else if (action == CFFS_DIRECTORY_SPLITENTRY) {
        embdirent_t *newDirent;
        int splitspace = param2;
        int extraspace;

        extraspace = (dirent->type == (char)0) ? dirent->entryLen : (dirent->entryLen - embdirentsize(dirent));
        if ((extraspace < SIZEOF_EMBDIRENT_T) || (extraspace < splitspace)) {
            printf ("sys_fsupdate_directory (%d): not enough extra space (%d) (wanted %d)\n", action, extraspace, splitspace);
            return (-E_INVAL);
        }

        if (splitspace == 0) {
            printf ("sys_fsupdate_directory (%d): bad splitspace (%d) (extraspace %d)\n", action, splitspace, extraspace);
            return (-E_INVAL);
        }

        dirent->entryLen -= splitspace;
        newDirent = (embdirent_t *) ((u_int)dirent + dirent->entryLen);
        if (newDirent != dirent) {
            newDirent->preventryLen = dirent->entryLen;
        }
        newDirent->entryLen = splitspace;
        newDirent->type = 0;
        newDirent->nameLen = 0;
        newDirent->name[0] = (char) 0;
        if (((u_int)newDirent + newDirent->entryLen) % CFFS_EMBDIR_SECTOR_SPACEFORNAMES) {
            dirent = (embdirent_t *) ((char *)newDirent + newDirent->entryLen);
            dirent->preventryLen = splitspace;
        }
        /* XXX % */
        //      ret = (param1 - (param1 % BLOCK_SIZE)) + ((u_int)newDirent - (u_int)dirBlock);
        return ((u_int )newDirent);

        /*************************** CFFS_DIRECTORY_SETNAME ************************/

    } else if (action == CFFS_DIRECTORY_SETNAME) {
        //     char *name = (char *) trup(param2); /* XXX */
        char name[256];

        u_int namelen = param3;
        dinode_t *dirDInode = translate_address (&arg->ref_param4);

        /* XXX -- I thought we only reserved < 128 bytes for names? */
        if (namelen > 256) {
            printf ("sys_fsupdate_directory (%d): name too long (%d)\n", action, namelen);
            return (-E_INVAL);
        }

        if (cffsd_copyin (client_eid, param2, (uint )name, namelen) == -1)
            return (-E_INVAL);

        if ((dirDInode == NULL) || (dirDInode->dinodeNum == 0)) {
            return (-E_INVAL);
        }

        /* Note: param5 is fsdev in this case, which should be discoverable */
        /* from the dinode's identity...                                    */
        if ((dirent->type != 0) && (!isNameUnique(param5, dirDInode, name, namelen))) {
            printf ("sys_fsupdate_directory (%d): non-unique name specified (%d)\n", action, namelen);
            return (-E_INVAL);
        }

        bcopy(name, dirent->name, namelen);
        //      dirent->name[namelen] = (char) 0;
        dirent->nameLen = namelen;

        /*************************** CFFS_DIRECTORY_MERGEENTRY ************************/

    } else if (action == CFFS_DIRECTORY_MERGEENTRY) {
        embdirent_t *next = NULL;
        int maxleft = CFFS_EMBDIR_SECTOR_SPACEFORNAMES - (param1 % CFFS_EMBDIR_SECTOR_SIZE);
        int extraspace = 0;

        while ((extraspace < param2) && (extraspace < maxleft)) {
            next = (embdirent_t *) ((char *)dirent + dirent->entryLen);
            if (next->type != 0) {
                break;
            }
            extraspace += next->entryLen;
        }

        if (extraspace != param2) {
            printf ("sys_fsupdate_directory (%d): mismatched extraspaces (%d != %d) (maxleft %d)\n", action, extraspace, param2, maxleft);
            printf ("next %p, next->entryLen %d\n", next, ((next) ? (next->entryLen) : -1));
            return (-E_INVAL);
        }

        dirent->entryLen += extraspace;
        next = (embdirent_t *) ((char *)dirent + dirent->entryLen);
        if ((u_int) next % CFFS_EMBDIR_SECTOR_SPACEFORNAMES) {
            next->preventryLen = dirent->entryLen;
        }

        /*************************** CFFS_DIRECTORY_SHIFTENTRY ************************/

    } else if (action == CFFS_DIRECTORY_SHIFTENTRY) {

        /********* Not currently supported! ************/
        assert (0);

#if 0
        embdirent_t *tmp;
        int extraspace;

        if ((-param2 > (param1 % CFFS_EMBDIR_SECTOR_SIZE)) || ((param2 + (param1 % CFFS_EMBDIR_SECTOR_SIZE)) >= (CFFS_EMBDIR_SECTOR_SPACEFORNAMES - SIZEOF_EMBDIRENT_T))) {
            printf ("sys_fsupdate_directory (%d): sizes don't work (currOff %d, move %d)\n", action, (param1 % BLOCK_SIZE), param2);
            return (-E_INVAL);
        }

        if (param2 <= 0) {
            tmp = (embdirent_t *) ((char *)dirent - dirent->preventryLen);
            extraspace = (tmp->type == (char)0) ? tmp->entryLen : tmp->entryLen - embdirentsize(tmp);
            if (extraspace < (-param2)) {
                printf ("sys_fsupdate_directory (%d): not enough extra space (%d < %d)\n", action, extraspace, param2);
                return (-E_INVAL);
            }
            tmp->entryLen -= (-param2);
            dirent->preventryLen = tmp->entryLen;
            dirent->entryLen += (-param2);
            bcopy ((char *) dirent, ((char *)dirent - (-param2)), embdirentsize(dirent));
            tmp = (embdirent_t *) ((char *)dirent + dirent->entryLen);
            if ((u_int) tmp % CFFS_EMBDIR_SECTOR_SPACEFORNAMES) {
                tmp->preventryLen = dirent->entryLen;
            }

        } else {
            tmp = (embdirent_t *) ((char *)dirent - dirent->preventryLen);
            extraspace = dirent->entryLen - embdirentsize(dirent);
            if (extraspace < param2) {
                printf ("sys_fsupdate_directory (%d): not enough extra space (%d < %d)\n", action, extraspace, param2);
                return (-E_INVAL);
            }
            tmp->entryLen += param2;
            dirent->preventryLen = tmp->entryLen;
            dirent->entryLen -= param2;
            bcopy ((char *)dirent, ((char *)dirent + param2), embdirentsize(dirent));
            dirent = (embdirent_t *) ((char *)dirent + tmp->entryLen);
            tmp = (embdirent_t *) ((char *)dirent + dirent->entryLen);
            if ((u_int) tmp % CFFS_EMBDIR_SECTOR_SPACEFORNAMES) {
                tmp->preventryLen = dirent->entryLen;
            }
        }
#endif

        /*************************** CFFS_DIRECTORY_SETINODENUM ***********************/

    } else if (action == CFFS_DIRECTORY_SETINODENUM) {
        u_int inodeNum = param2;

        /* no restrictions is directory entry is not currently live */
        if (dirent->type == 0) {
            dirent->inodeNum = inodeNum;

            /* this case causes a change in which inode a dirent points to.      */
            /* because the dirent is live, it must always point to a live inode. */
        } else {
            dinode_t *olddinode;
            dinode_t *newdinode;

            if (inodeNum == 0) {
                printf ("sys_fsupdate_directory (%d): can't set inodeNum to 0 is live dirent\n", action);
                return (-E_INVAL);
            }

            /*
                if ((param3 == 0) || (param4 == 0)) {
                   printf ("sys_fsupdate_directory (%d): passed NULL for a cheat variable (%d, %d)\n", action, param3, param4);
                   return (-E_INVAL);
                }
            */
            /* it is a bug in FS code to have valid dirent with 0 for an inodeNum */
            assert (dirent->inodeNum != 0);

            /* this should be retrievable from dirent->inodeNum, which identifies */
            /* the containing disk block -- which must be a directory block.      */
            olddinode = translate_address (&arg->ref_param3);
            if (olddinode->dinodeNum != dirent->inodeNum) {
                printf ("sys_fsupdate_directory (%d): mismatching old inodeNums (%d != %d)\n", action, olddinode->dinodeNum, dirent->inodeNum);
                return (-E_INVAL);
            }

            /* this should be retrievable from inodeNum, which identifies the */
            /* containing disk block -- which must be a directory block.     */
            newdinode = translate_address (&arg->ref_param4);
            if (newdinode->dinodeNum != inodeNum) {
                printf ("sys_fsupdate_directory (%d): mismatching old inodeNums (%d != %d)\n", action, newdinode->dinodeNum, inodeNum);
                return (-E_INVAL);
            }

            if ((olddinode->type != newdinode->type) && ((cffs_dinode_isDir(olddinode)) || (cffs_dinode_isDir(newdinode)))) {
                printf ("sys_fsupdate_directory (%d): can't interchange a directory and non-directory (%x != %x)\n", action, olddinode->type, newdinode->type);
                return (-E_INVAL);
            }

            /* this rule helps get us around an ordering requirement!! */
            /* (i.e., if we handle ordering in some other way, it can  */
            /* go away...                                              */
            if (newdinode->linkCount < (cffs_dinode_isDir(newdinode) ? 2 : 1)) {
                printf ("sys_fsupdate_directory (%d): can't link up to disowned inode\n", action);
                return (-E_INVAL);
            }

            /* the big stickler here is that we need to be able to check whether */
            /* the caller has the ability to look at newdinode.  In particular,  */
            /* this requires execute permission on a directory that already      */
            /* contains an existing link.                                        */

            if ((olddinode) && (cffs_dinode_isDir(olddinode))) {
                /* must check that directory is actually empty... */
            }

            /* GROK - I'm pretty sure I've designed away all need for ordering here */
            olddinode->linkCount--;
            newdinode->linkCount++;
            dirent->inodeNum = inodeNum;
            dirent->type = newdinode->type >> 8;
        }

        /**************************** CFFS_DIRECTORY_SETTYPE **************************/

    } else if (action == CFFS_DIRECTORY_SETTYPE) {
Пример #19
0
// int cffsd_fsupdate_superblock (u_int sn, int action, struct superblock *superblock, u_int param1, u_int param2)
int serv_fsupdate_superblock (u_int client_eid, int action, struct cffsd_fsupdate_superblock_arg *arg)
{
    struct superblock *superblock;
    u_int param1 = arg->param1;
    u_int param2 = arg->param2;

    debug_request = 2;

    superblock = translate_address (&arg->superblock);

    StaticAssert (sizeof(struct superblock) == NBPG);
    StaticAssert (BLOCK_SIZE == NBPG);

    //   superblock = (struct superblock *) translate_address ((uint)superblock, NBPG);
    if (superblock == NULL) {
        return (-E_INVAL);
    }

    if (action == CFFS_SUPERBLOCK_SETDIRTY) {
        /* allow anyone to set dirty to a non-zero value at any time.    */
        /* However, must verify that there are no dirty blocks from this */
        /* file system before allowing anyone to set dirty to 0.         */
        superblock->dirty = param1;

    } else if (action == CFFS_SUPERBLOCK_SETROOTDINODENUM) {
        /* verify that the provided rootDInodeNum is in fact the correct     */
        /* system value -- we should know this based on the superblocks addr */
        superblock->rootDInodeNum = param1;

    } else if (action == CFFS_SUPERBLOCK_SETFSNAME) {
        /* verify that the provided fsname is in fact the correct value */
        /* -- should match XN's expectation...                          */
        /* Also, don't allow it to go out of bounds in superblock...    */
        //     char *str = (char *) trup(param1); /* XXX */
        strcpy (superblock->fsname, CFFS_FSNAME);
    } else if (action == CFFS_SUPERBLOCK_DELETE) {
        superblock->fsname[0] = 0;	/* just clear the name for now */
    } else if (action == CFFS_SUPERBLOCK_SETFSDEV) {
        /* verify that the provided fsdev is in fact the correct system value */
        /* -- XN should certainly know this...                                */
        superblock->fsdev = param1;

    } else if (action == CFFS_SUPERBLOCK_SETALLOCMAP) {
        /* this is a totally temporary call.  This field should be maintained */
        /* solely by XN...                                                    */
        superblock->allocMap = param1;

    } else if (action == CFFS_SUPERBLOCK_SETNUMBLOCKS) {
        /* this is a totally temporary call.  This field should be maintained */
        /* solely by XN...                                                    */
        superblock->numblocks = param1;

    } else if (action == CFFS_SUPERBLOCK_SETSIZE) {
        /* this is a totally temporary call.  This field should be maintained */
        /* solely by XN...                                                    */
        superblock->size = param1;

    } else if (action == CFFS_SUPERBLOCK_SETNUMALLOCED) {
        /* this is a totally temporary call.  This field should be maintained */
        /* by the ALLOCATE and DEALLOCATE methods...                          */
        superblock->numalloced = param1;

    } else if (action == CFFS_SUPERBLOCK_SETXNTYPE) {
        /* this is a totally temporary call.  This field should be maintained */
        /* and updated only by newfs!!...                                     */
        if ((param1 < 0) || (param1 >= CFFS_MAX_XNTYPES)) {
            printf ("sys_fsupdate_superblock (%d): bad typeno %d (NUM %d)\n", action, param1, CFFS_MAX_XNTYPES);
            return -E_INVAL;
        }
        superblock->xntypes[param1] = param2;

    } else if (action == CFFS_SUPERBLOCK_INIT) {
        /* this is a totally temporary call.  Just for when not using XN */
        bzero (superblock, BLOCK_SIZE);

    } else if (action == CFFS_SUPERBLOCK_SETBLK) {
        superblock->blk = param1;
    } else if (action == CFFS_SUPERBLOCK_SETQUOTA) {
        if (param1 > superblock->numblocks) {
            printf ("sys_fsupdate_superblock (%d): quota (%d) is bigger than available space (%d)\n", action, param1, superblock->numblocks);
            return -E_INVAL;
        }
        superblock->quota = param1;
    } else {
        printf ("sys_fsupdate_superblock: unknown action requested (%d)\n", action);
        return (-E_INVAL);
    }

    return (0);
}