/* 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); }