Exemple #1
0
/* called from the CRYPTO_GET_SOFT_INFO ioctl */
int
crypto_get_soft_info(caddr_t name, uint_t *count, crypto_mech_name_t **array)
{
	ddi_modhandle_t modh = NULL;
	kcf_provider_desc_t *provider;
	int rv;

	provider = kcf_prov_tab_lookup_by_name(name);
	if (provider == NULL) {
		if (in_soft_config_list(name)) {
			char *tmp;
			int name_len;

			/* strlen("crypto/") + NULL terminator == 8 */
			name_len = strlen(name);
			tmp = kmem_alloc(name_len + 8, KM_SLEEP);
			bcopy("crypto/", tmp, 7);
			bcopy(name, &tmp[7], name_len);
			tmp[name_len + 7] = '\0';

			modh = ddi_modopen(tmp, KRTLD_MODE_FIRST, NULL);
			kmem_free(tmp, name_len + 8);

			if (modh == NULL) {
				return (CRYPTO_ARGUMENTS_BAD);
			}

			provider = kcf_prov_tab_lookup_by_name(name);
			if (provider == NULL) {
				return (CRYPTO_ARGUMENTS_BAD);
			}
		} else {
			return (CRYPTO_ARGUMENTS_BAD);
		}
	}

	rv = dup_mech_names(provider, array, count, KM_SLEEP);
	KCF_PROV_REFRELE(provider);
	if (modh != NULL)
		(void) ddi_modclose(modh);
	return (rv);
}
/* write firmware segments into device through control endpoint */
static int
wusb_df_fw_download(wusb_df_state_t *wusb_dfp)
{
	int		error = USB_SUCCESS;
	size_t		size  = 0, record_cnt = 0;
	unsigned char	*pdata, *data_end;
	unsigned char	*firmware_image;
	fw_dsc_t	*pdsc = NULL, *rcd_head = NULL, *tmpr = NULL;
	unsigned int	remaining_size;
	int		rv = 0;
	ddi_modhandle_t modp;
	char *firm_start;

	USB_DPRINTF_L3(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
	    "Download firmware: %s", wusb_fwmod);

	/* allow user specify firmware in .conf? */

	/* see elfwrap(1) for how to turn firmware into loadable module */
	modp = ddi_modopen(wusb_fwmod, KRTLD_MODE_FIRST, &rv);
	if (modp == NULL) {
		USB_DPRINTF_L2(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
		    "module %s not found", wusb_fwmod);

		error = USB_FAILURE;
		goto checkstatus;
	}

	rv = wusbdf_mod_loadsym(wusb_dfp, modp, wusb_fwmod, wusb_fwsym1,
	    &firm_start, &size);
	if (rv != 0) {
		USB_DPRINTF_L2(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
		    "module(%s) loadsym error", wusb_fwmod);

		error = USB_FAILURE;
		goto checkstatus;
	}

	if (size >= MAX_DAT_FILE_SIZE) {
		USB_DPRINTF_L2(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
		    "file size too big");

		error = USB_FAILURE;
		goto checkstatus;
	} else {
		firmware_image = (unsigned char *)kmem_alloc(size, KM_SLEEP);

		if (!firmware_image) {
			USB_DPRINTF_L2(PRINT_MASK_ATTA,
			    wusb_dfp->wusb_df_log_hdl, "malloc failed");

			error = USB_FAILURE;
			goto checkstatus;
		}

		(void) memcpy(firmware_image, firm_start, size);
	}

	USB_DPRINTF_L3(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
	    "file size = %d", (int)size);

	/*
	 * close the module, return if 1) fail to close or 2) encounter error
	 * when getting above symbol
	 */
checkstatus:
	if (modp != NULL)
		rv = ddi_modclose(modp);

	if ((rv != 0) || (error != USB_SUCCESS)) {
		USB_DPRINTF_L2(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
		    "modclose(%s) error", wusb_fwmod);

		return (USB_FAILURE);
	}

	/*
	 * BIN firmware has this format:
	 * address(4B) + length(4B) + data(Length Bytes) ... repeat
	 */
	pdata = firmware_image;
	data_end = firmware_image + size;
	while (pdata < data_end) {
		error = USB_FAILURE;
		pdsc = (fw_dsc_t *)kmem_zalloc(sizeof (fw_dsc_t), KM_SLEEP);

		/* hdr_offset = pdata - firmware_image; */
		remaining_size = data_end - pdata;

		if ((pdata + 8) > data_end) {
			kmem_free(pdsc, sizeof (fw_dsc_t));
			free_fw_dscs(rcd_head);
			break;
		}

		pdsc->next = NULL;
		pdsc->addr = char2int32(pdata);
		pdsc->size = 4 * char2int32(pdata + 4);
		pdsc->data = pdata + 8;
		if (pdsc->size > remaining_size) {
			kmem_free(pdsc, sizeof (fw_dsc_t));
			free_fw_dscs(rcd_head);
			break;
		}
		USB_DPRINTF_L3(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
		    "address = 0x%x, length = 0x%x, "
		    "first 4 byte is : 0x%02x 0x%02x 0x%02x 0x%02x",
		    pdsc->addr, (int)pdsc->size, pdsc->data[0], pdsc->data[1],
		    pdsc->data[2], pdsc->data[3]);

		pdata += 8 + pdsc->size;
		if (rcd_head == NULL) {
			rcd_head = pdsc;
		} else {
			tmpr->next = pdsc;
		}

		tmpr = pdsc; /* tmp record */
		record_cnt ++;
		error = USB_SUCCESS;
	}

	USB_DPRINTF_L3(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
	    "Start download firmware ...");
	for (pdsc = rcd_head; pdsc != NULL; pdsc = pdsc->next) {
		error = wusb_df_send_data(wusb_dfp, pdsc->addr,
		    pdsc->data, pdsc->size);
		if (error != USB_SUCCESS) {

			USB_DPRINTF_L2(PRINT_MASK_ATTA,
			    wusb_dfp->wusb_df_log_hdl, "Download failure!");
			break;
		}

		delay(drv_usectohz(1000));
	}

	USB_DPRINTF_L2(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
	    "Download firmware end.");

	free_fw_dscs(rcd_head);
	kmem_free(firmware_image, size);

	return (error);
}