示例#1
0
static int fec_init(struct eth_device *dev, bd_t *bd)
#endif
{
#ifdef CONFIG_DM_ETH
	struct fec_priv *fec = dev_get_priv(dev);
#else
	struct fec_priv *fec = (struct fec_priv *)dev->priv;
#endif
	uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop;
	int i;

	/* Initialize MAC address */
#ifdef CONFIG_DM_ETH
	fecmxc_set_hwaddr(dev);
#else
	fec_set_hwaddr(dev);
#endif

	/* Setup transmit descriptors, there are two in total. */
	fec_tbd_init(fec);

	/* Setup receive descriptors. */
	fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE);

	fec_reg_setup(fec);

	if (fec->xcv_type != SEVENWIRE)
		fec_mii_setspeed(fec->bus->priv);

	/* Set Opcode/Pause Duration Register */
	writel(0x00010020, &fec->eth->op_pause);	/* FIXME 0xffff0020; */
	writel(0x2, &fec->eth->x_wmrk);

	/* Set multicast address filter */
	writel(0x00000000, &fec->eth->gaddr1);
	writel(0x00000000, &fec->eth->gaddr2);

	/* Do not access reserved register for i.MX6UL */
	if (!is_mx6ul()) {
		/* clear MIB RAM */
		for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
			writel(0, i);

		/* FIFO receive start register */
		writel(0x520, &fec->eth->r_fstart);
	}

	/* size and address of each buffer */
	writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
	writel((uint32_t)fec->tbd_base, &fec->eth->etdsr);
	writel((uint32_t)fec->rbd_base, &fec->eth->erdsr);

#ifndef CONFIG_PHYLIB
	if (fec->xcv_type != SEVENWIRE)
		miiphy_restart_aneg(dev);
#endif
	fec_open(dev);
	return 0;
}
示例#2
0
文件: fec_mxc.c 项目: Apaisal/u-boot
static int fec_init(struct eth_device *dev, bd_t* bd)
{
	uint32_t base;
	struct fec_priv *fec = (struct fec_priv *)dev->priv;
	uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop;
	uint32_t rcntrl;
	int i;

	/* Initialize MAC address */
	fec_set_hwaddr(dev);

	/*
	 * reserve memory for both buffer descriptor chains at once
	 * Datasheet forces the startaddress of each chain is 16 byte
	 * aligned
	 */
	if (fec->base_ptr == NULL)
		fec->base_ptr = malloc((2 + FEC_RBD_NUM) *
				sizeof(struct fec_bd) + DB_ALIGNMENT);
	base = (uint32_t)fec->base_ptr;
	if (!base) {
		puts("fec_mxc: not enough malloc memory\n");
		return -ENOMEM;
	}
	memset((void *)base, 0, (2 + FEC_RBD_NUM) *
			sizeof(struct fec_bd) + DB_ALIGNMENT);
	base += (DB_ALIGNMENT-1);
	base &= ~(DB_ALIGNMENT-1);

	fec->rbd_base = (struct fec_bd *)base;

	base += FEC_RBD_NUM * sizeof(struct fec_bd);

	fec->tbd_base = (struct fec_bd *)base;

	/*
	 * Set interrupt mask register
	 */
	writel(0x00000000, &fec->eth->imask);

	/*
	 * Clear FEC-Lite interrupt event register(IEVENT)
	 */
	writel(0xffffffff, &fec->eth->ievent);


	/*
	 * Set FEC-Lite receive control register(R_CNTRL):
	 */

	/* Start with frame length = 1518, common for all modes. */
	rcntrl = PKTSIZE << FEC_RCNTRL_MAX_FL_SHIFT;
	if (fec->xcv_type == SEVENWIRE)
		rcntrl |= FEC_RCNTRL_FCE;
	else if (fec->xcv_type == RGMII)
		rcntrl |= FEC_RCNTRL_RGMII;
	else if (fec->xcv_type == RMII)
		rcntrl |= FEC_RCNTRL_RMII;
	else	/* MII mode */
		rcntrl |= FEC_RCNTRL_FCE | FEC_RCNTRL_MII_MODE;

	writel(rcntrl, &fec->eth->r_cntrl);

	if (fec->xcv_type == MII10 || fec->xcv_type == MII100)
		fec_mii_setspeed(fec);

	/*
	 * Set Opcode/Pause Duration Register
	 */
	writel(0x00010020, &fec->eth->op_pause);	/* FIXME 0xffff0020; */
	writel(0x2, &fec->eth->x_wmrk);
	/*
	 * Set multicast address filter
	 */
	writel(0x00000000, &fec->eth->gaddr1);
	writel(0x00000000, &fec->eth->gaddr2);


	/* clear MIB RAM */
	for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
		writel(0, i);

	/* FIFO receive start register */
	writel(0x520, &fec->eth->r_fstart);

	/* size and address of each buffer */
	writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
	writel((uint32_t)fec->tbd_base, &fec->eth->etdsr);
	writel((uint32_t)fec->rbd_base, &fec->eth->erdsr);

	/*
	 * Initialize RxBD/TxBD rings
	 */
	if (fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE) < 0) {
		free(fec->base_ptr);
		fec->base_ptr = NULL;
		return -ENOMEM;
	}
	fec_tbd_init(fec);


	if (fec->xcv_type != SEVENWIRE)
		miiphy_restart_aneg(dev);

	fec_open(dev);
	return 0;
}
// prepares the verity enabled (MF_VERIFY / MF_VERIFYATBOOT) fstab record for
// mount. The 'wait_for_verity_dev' parameter makes this function wait for the
// verity device to get created before return
int fs_mgr_setup_verity(FstabEntry* entry, bool wait_for_verity_dev) {
    int retval = FS_MGR_SETUP_VERITY_FAIL;
    int fd = -1;
    std::string verity_blk_name;
    struct fec_handle *f = NULL;
    struct fec_verity_metadata verity;
    struct verity_table_params params = { .table = NULL };

    const std::string mount_point(basename(entry->mount_point.c_str()));
    bool verified_at_boot = false;

    android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();

    if (fec_open(&f, entry->blk_device.c_str(), O_RDONLY, FEC_VERITY_DISABLE, FEC_DEFAULT_ROOTS) <
        0) {
        PERROR << "Failed to open '" << entry->blk_device << "'";
        return retval;
    }

    // read verity metadata
    if (fec_verity_get_metadata(f, &verity) < 0) {
        PERROR << "Failed to get verity metadata '" << entry->blk_device << "'";
        // Allow verity disabled when the device is unlocked without metadata
        if (fs_mgr_is_device_unlocked()) {
            retval = FS_MGR_SETUP_VERITY_SKIPPED;
            LWARNING << "Allow invalid metadata when the device is unlocked";
        }
        goto out;
    }

#ifdef ALLOW_ADBD_DISABLE_VERITY
    if (verity.disabled) {
        retval = FS_MGR_SETUP_VERITY_DISABLED;
        LINFO << "Attempt to cleanly disable verity - only works in USERDEBUG/ENG";
        goto out;
    }
#endif

    // read ecc metadata
    if (fec_ecc_get_metadata(f, &params.ecc) < 0) {
        params.ecc.valid = false;
    }

    params.ecc_dev = entry->blk_device.c_str();

    if (load_verity_state(*entry, &params.mode) < 0) {
        /* if accessing or updating the state failed, switch to the default
         * safe mode. This makes sure the device won't end up in an endless
         * restart loop, and no corrupted data will be exposed to userspace
         * without a warning. */
        params.mode = VERITY_MODE_EIO;
    }

    if (!verity.table) {
        goto out;
    }

    params.table = strdup(verity.table);
    if (!params.table) {
        goto out;
    }

    // verify the signature on the table
    if (verify_verity_signature(verity) < 0) {
        // Allow signature verification error when the device is unlocked
        if (fs_mgr_is_device_unlocked()) {
            retval = FS_MGR_SETUP_VERITY_SKIPPED;
            LWARNING << "Allow signature verification error when the device is unlocked";
            goto out;
        }
        if (params.mode == VERITY_MODE_LOGGING) {
            // the user has been warned, allow mounting without dm-verity
            retval = FS_MGR_SETUP_VERITY_SKIPPED;
            goto out;
        }

        // invalidate root hash and salt to trigger device-specific recovery
        if (invalidate_table(params.table, verity.table_length) < 0) {
            goto out;
        }
    }

    LINFO << "Enabling dm-verity for " << mount_point.c_str()
          << " (mode " << params.mode << ")";

    // Update the verity params using the actual block device path
    update_verity_table_blk_device(entry->blk_device, &params.table,
                                   entry->fs_mgr_flags.slot_select);

    // load the verity mapping table
    if (load_verity_table(dm, mount_point, verity.data_size, &params, format_verity_table) == 0) {
        goto loaded;
    }

    if (params.ecc.valid) {
        // kernel may not support error correction, try without
        LINFO << "Disabling error correction for " << mount_point.c_str();
        params.ecc.valid = false;

        if (load_verity_table(dm, mount_point, verity.data_size, &params, format_verity_table) == 0) {
            goto loaded;
        }
    }

    // try the legacy format for backwards compatibility
    if (load_verity_table(dm, mount_point, verity.data_size, &params, format_legacy_verity_table) ==
        0) {
        goto loaded;
    }

    if (params.mode != VERITY_MODE_EIO) {
        // as a last resort, EIO mode should always be supported
        LINFO << "Falling back to EIO mode for " << mount_point.c_str();
        params.mode = VERITY_MODE_EIO;

        if (load_verity_table(dm, mount_point, verity.data_size, &params,
                              format_legacy_verity_table) == 0) {
            goto loaded;
        }
    }

    LERROR << "Failed to load verity table for " << mount_point.c_str();
    goto out;

loaded:
    if (!dm.GetDmDevicePathByName(mount_point, &verity_blk_name)) {
        LERROR << "Couldn't get verity device number!";
        goto out;
    }

    // mark the underlying block device as read-only
    fs_mgr_set_blk_ro(entry->blk_device);

    // Verify the entire partition in one go
    // If there is an error, allow it to mount as a normal verity partition.
    if (entry->fs_mgr_flags.verify_at_boot) {
        LINFO << "Verifying partition " << entry->blk_device << " at boot";
        int err = read_partition(verity_blk_name.c_str(), verity.data_size);
        if (!err) {
            LINFO << "Verified verity partition " << entry->blk_device << " at boot";
            verified_at_boot = true;
        }
    }

    // assign the new verity block device as the block device
    if (!verified_at_boot) {
        entry->blk_device = verity_blk_name;
    } else if (!dm.DeleteDevice(mount_point)) {
        LERROR << "Failed to remove verity device " << mount_point.c_str();
        goto out;
    }

    // make sure we've set everything up properly
    if (wait_for_verity_dev && !fs_mgr_wait_for_file(entry->blk_device, 1s)) {
        goto out;
    }

    retval = FS_MGR_SETUP_VERITY_SUCCESS;

out:
    if (fd != -1) {
        close(fd);
    }

    fec_close(f);
    free(params.table);

    return retval;
}
static int compare_last_signature(const FstabEntry& entry, int* match) {
    char tag[METADATA_TAG_MAX_LENGTH + 1];
    int fd = -1;
    int rc = -1;
    off64_t offset = 0;
    struct fec_handle *f = NULL;
    struct fec_verity_metadata verity;
    uint8_t curr[SHA256_DIGEST_LENGTH];
    uint8_t prev[SHA256_DIGEST_LENGTH];

    *match = 1;

    if (fec_open(&f, entry.blk_device.c_str(), O_RDONLY, FEC_VERITY_DISABLE, FEC_DEFAULT_ROOTS) ==
        -1) {
        PERROR << "Failed to open '" << entry.blk_device << "'";
        return rc;
    }

    // read verity metadata
    if (fec_verity_get_metadata(f, &verity) == -1) {
        PERROR << "Failed to get verity metadata '" << entry.blk_device << "'";
        goto out;
    }

    SHA256(verity.signature, sizeof(verity.signature), curr);

    if (snprintf(tag, sizeof(tag), VERITY_LASTSIG_TAG "_%s", basename(entry.mount_point.c_str())) >=
        (int)sizeof(tag)) {
        LERROR << "Metadata tag name too long for " << entry.mount_point;
        goto out;
    }

    if (metadata_find(entry.verity_loc.c_str(), tag, SHA256_DIGEST_LENGTH, &offset) < 0) {
        goto out;
    }

    fd = TEMP_FAILURE_RETRY(open(entry.verity_loc.c_str(), O_RDWR | O_SYNC | O_CLOEXEC));

    if (fd == -1) {
        PERROR << "Failed to open " << entry.verity_loc;
        goto out;
    }

    if (TEMP_FAILURE_RETRY(pread64(fd, prev, sizeof(prev), offset)) != sizeof(prev)) {
        PERROR << "Failed to read " << sizeof(prev) << " bytes from " << entry.verity_loc
               << " offset " << offset;
        goto out;
    }

    *match = !memcmp(curr, prev, SHA256_DIGEST_LENGTH);

    if (!*match) {
        /* update current signature hash */
        if (TEMP_FAILURE_RETRY(pwrite64(fd, curr, sizeof(curr),
                offset)) != sizeof(curr)) {
            PERROR << "Failed to write " << sizeof(curr) << " bytes to " << entry.verity_loc
                   << " offset " << offset;
            goto out;
        }
    }

    rc = 0;

out:
    fec_close(f);
    return rc;
}
示例#5
0
static int fec_init(struct eth_device *dev, bd_t* bd)
{
	struct fec_priv *fec = (struct fec_priv *)dev->priv;
	uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop;
	uint32_t size;
	int i, ret;

	/* Initialize MAC address */
	fec_set_hwaddr(dev);

	/*
	 * Allocate transmit descriptors, there are two in total. This
	 * allocation respects cache alignment.
	 */
	if (!fec->tbd_base) {
		size = roundup(2 * sizeof(struct fec_bd),
				ARCH_DMA_MINALIGN);
		fec->tbd_base = memalign(ARCH_DMA_MINALIGN, size);
		if (!fec->tbd_base) {
			ret = -ENOMEM;
			goto err1;
		}
		memset(fec->tbd_base, 0, size);
		fec_tbd_init(fec);
	}

	/*
	 * Allocate receive descriptors. This allocation respects cache
	 * alignment.
	 */
	if (!fec->rbd_base) {
		size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd),
				ARCH_DMA_MINALIGN);
		fec->rbd_base = memalign(ARCH_DMA_MINALIGN, size);
		if (!fec->rbd_base) {
			ret = -ENOMEM;
			goto err2;
		}
		memset(fec->rbd_base, 0, size);
		/*
		 * Initialize RxBD ring
		 */
		if (fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE) < 0) {
			ret = -ENOMEM;
			goto err3;
		}
		flush_dcache_range((unsigned)fec->rbd_base,
				   (unsigned)fec->rbd_base + size);
	}

	fec_reg_setup(fec);

	if (fec->xcv_type != SEVENWIRE)
		fec_mii_setspeed(fec->bus->priv);

	/*
	 * Set Opcode/Pause Duration Register
	 */
	writel(0x00010020, &fec->eth->op_pause);	/* FIXME 0xffff0020; */
	writel(0x2, &fec->eth->x_wmrk);
	/*
	 * Set multicast address filter
	 */
	writel(0x00000000, &fec->eth->gaddr1);
	writel(0x00000000, &fec->eth->gaddr2);


	/* clear MIB RAM */
	for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
		writel(0, i);

	/* FIFO receive start register */
	writel(0x520, &fec->eth->r_fstart);

	/* size and address of each buffer */
	writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
	writel((uint32_t)fec->tbd_base, &fec->eth->etdsr);
	writel((uint32_t)fec->rbd_base, &fec->eth->erdsr);

#ifndef CONFIG_PHYLIB
	if (fec->xcv_type != SEVENWIRE)
		miiphy_restart_aneg(dev);
#endif
	fec_open(dev);
	return 0;

err3:
	free(fec->rbd_base);
err2:
	free(fec->tbd_base);
err1:
	return ret;
}