bool device_node::_AlwaysRegisterDynamic() { uint16 type = 0; uint16 subType = 0; get_attr_uint16(this, B_DEVICE_TYPE, &type, false); get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false); return type == PCI_serial_bus || type == PCI_bridge || type == 0; // TODO: we may want to be a bit more specific in the future }
status_t device_node::Probe(const char* devicePath, uint32 updateCycle) { if ((fFlags & NODE_FLAG_DEVICE_REMOVED) != 0 || updateCycle == fLastUpdateCycle) return B_OK; status_t status = InitDriver(); if (status < B_OK) return status; MethodDeleter<device_node, bool> uninit(this, &device_node::UninitDriver); if ((fFlags & B_FIND_CHILD_ON_DEMAND) != 0) { bool matches = false; uint16 type = 0; uint16 subType = 0; if (get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) == B_OK && get_attr_uint16(this, B_DEVICE_TYPE, &type, false) == B_OK) { // Check if this node matches the device path // TODO: maybe make this extendible via settings file? if (!strcmp(devicePath, "disk")) { matches = type == PCI_mass_storage; } else if (!strcmp(devicePath, "audio")) { matches = type == PCI_multimedia && (subType == PCI_audio || subType == PCI_hd_audio); } else if (!strcmp(devicePath, "net")) { matches = type == PCI_network; } else if (!strcmp(devicePath, "graphics")) { matches = type == PCI_display; } else if (!strcmp(devicePath, "video")) { matches = type == PCI_multimedia && subType == PCI_video; } } else { // This driver does not support types, but still wants to its // children explored on demand only. matches = true; sGenericContextPath = devicePath; } if (matches) { fLastUpdateCycle = updateCycle; // This node will be probed in this update cycle status = _Probe(); sGenericContextPath = NULL; return status; } return B_OK; } NodeList::Iterator iterator = fChildren.GetIterator(); while (iterator.HasNext()) { device_node* child = iterator.Next(); status = child->Probe(devicePath, updateCycle); if (status != B_OK) return status; } return B_OK; }
status_t device_node::_GetNextDriverPath(void*& cookie, KPath& _path) { Stack<KPath*>* stack = NULL; if (cookie == NULL) { // find all paths and add them stack = new(std::nothrow) Stack<KPath*>(); if (stack == NULL) return B_NO_MEMORY; StackDeleter<KPath*> stackDeleter(stack); bool generic = false; uint16 type = 0; uint16 subType = 0; uint16 interface = 0; if (get_attr_uint16(this, B_DEVICE_TYPE, &type, false) != B_OK || get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) != B_OK) generic = true; get_attr_uint16(this, B_DEVICE_INTERFACE, &interface, false); // TODO: maybe make this extendible via settings file? switch (type) { case PCI_mass_storage: switch (subType) { case PCI_scsi: _AddPath(*stack, "busses", "scsi"); _AddPath(*stack, "busses", "virtio"); break; case PCI_ide: _AddPath(*stack, "busses", "ata"); _AddPath(*stack, "busses", "ide"); break; case PCI_sata: // TODO: check for ahci interface _AddPath(*stack, "busses", "scsi"); _AddPath(*stack, "busses", "ata"); _AddPath(*stack, "busses", "ide"); break; default: _AddPath(*stack, "busses"); break; } break; case PCI_serial_bus: switch (subType) { case PCI_firewire: _AddPath(*stack, "busses", "firewire"); break; case PCI_usb: _AddPath(*stack, "busses", "usb"); break; default: _AddPath(*stack, "busses"); break; } break; case PCI_network: _AddPath(*stack, "drivers", "net"); _AddPath(*stack, "busses", "virtio"); break; case PCI_display: _AddPath(*stack, "drivers", "graphics"); break; case PCI_multimedia: switch (subType) { case PCI_audio: case PCI_hd_audio: _AddPath(*stack, "drivers", "audio"); break; case PCI_video: _AddPath(*stack, "drivers", "video"); break; default: _AddPath(*stack, "drivers"); break; } break; default: if (sRootNode == this) { _AddPath(*stack, "busses/pci"); _AddPath(*stack, "bus_managers"); } else if (!generic) { _AddPath(*stack, "busses", "virtio"); _AddPath(*stack, "drivers"); } else { // For generic drivers, we only allow busses when the // request is more specified if (sGenericContextPath != NULL && (!strcmp(sGenericContextPath, "disk") || !strcmp(sGenericContextPath, "ports") || !strcmp(sGenericContextPath, "bus"))) { _AddPath(*stack, "busses"); } _AddPath(*stack, "drivers", sGenericContextPath); _AddPath(*stack, "busses/scsi"); _AddPath(*stack, "busses/random"); } break; } stackDeleter.Detach(); cookie = (void*)stack; } else stack = static_cast<Stack<KPath*>*>(cookie); KPath* path; if (stack->Pop(&path)) { _path.Adopt(*path); delete path; return B_OK; } delete stack; return B_ENTRY_NOT_FOUND; }
static int execute_query(parser_context *p_context, const char **attr) { const char *type = 0; int ret = get_attr_str(attr, "type", &type); if(CPI_FAILED(ret)) { return ret; } /*! handle PIDX query */ if(strncmp(type, "pidx", strlen("pidx")) == 0) { uint16_t key_id = 0; /*! retrieve key_id */ { ret = get_attr_uint16(attr, "key_id", &key_id); if(CPI_FAILED(ret)) { return ret; } } ret = cpi_get_putative_id(p_context->p_cpi, key_id, p_context->p_cpi->tmp_buff_xml); if(CPI_FAILED(ret)) { output_condition_failure(p_context, type, ret); } else { output_condition_success_beg(p_context, type); strncat(p_context->out_xml_str, p_context->p_cpi->tmp_buff_xml, max_size); output_condition_success_end(p_context); } } /*! handle PKEY query */ else if(strncmp(type, "pkey", strlen("pkey")) == 0) { uint16_t key_id = 0; /*! retrieve key_id */ { ret = get_attr_uint16(attr, "key_id", &key_id); if(CPI_FAILED(ret)) { return ret; } } ret = cpi_get_public_key(p_context->p_cpi, key_id, p_context->p_cpi->tmp_buff_xml); if(CPI_FAILED(ret)) { output_condition_failure(p_context, type, ret); } else { output_condition_success_beg(p_context, type); strncat(p_context->out_xml_str, "\n", max_size); strncat(p_context->out_xml_str, p_context->p_cpi->tmp_buff_xml, max_size); strncat(p_context->out_xml_str, " ", max_size); output_condition_success_end(p_context); } } /*! handle VERS query */ else if(strncmp(type, "vers", strlen("vers")) == 0) { uint16_t major = 0, minor = 0, fix = 0; ret = cpi_get_version_number(p_context->p_cpi, &major, &minor, &fix); if(CPI_FAILED(ret)) { output_condition_failure(p_context, type, ret); } else { /*! generate version string major.minor.fix (e.g. 4.2.0) */ sprintf(p_context->p_cpi->tmp_buff_xml, "%d.%d.%d", major, minor, fix); output_condition_success_beg(p_context, type); strncat(p_context->out_xml_str, p_context->p_cpi->tmp_buff_xml, max_size); output_condition_success_end(p_context); } } /*! handle TIME query */ else if(strncmp(type, "time", strlen("time")) == 0) { uint32_t cur_time = 0; ret = cpi_get_current_time(p_context->p_cpi, &cur_time); if(CPI_FAILED(ret)) { output_condition_failure(p_context, type, ret); } else { /*! convert time to string format */ sprintf(p_context->p_cpi->tmp_buff_xml, "%u", cur_time); output_condition_success_beg(p_context, type); strncat(p_context->out_xml_str, p_context->p_cpi->tmp_buff_xml, max_size); output_condition_success_end(p_context); } } /*! handle CKEY query */ else if(strncmp(type, "ckey", strlen("ckey")) == 0) { uint32_t cur_oki = 0; ret = cpi_get_owner_key_index(p_context->p_cpi, &cur_oki); if(CPI_FAILED(ret)) { output_condition_failure(p_context, type, ret); } else { /*! convert owner key to string format */ sprintf(p_context->p_cpi->tmp_buff_xml, "%u", cur_oki); output_condition_success_beg(p_context, type); strncat(p_context->out_xml_str, p_context->p_cpi->tmp_buff_xml, max_size); output_condition_success_end(p_context); } } /*! handle SNUM query */ else if(strncmp(type, "snum", strlen("snum")) == 0) { uint8_t serial_number[CPI_SERIAL_NUMBER_SIZE] = { 0 }; ret = cpi_get_serial_number(p_context->p_cpi, serial_number); if(CPI_FAILED(ret)) { output_condition_failure(p_context, type, ret); } else { /*! blank out temporary buffer */ strcpy(p_context->p_cpi->tmp_buff_xml, ""); /*! convert serial number to string format */ { char buff[8]; int v; for(v=0;v<CPI_SERIAL_NUMBER_SIZE;v++) { sprintf(buff, "%.02X", (uint32_t)serial_number[v]); strncat(p_context->p_cpi->tmp_buff_xml, buff, max_size); } } output_condition_success_beg(p_context, type); strncat(p_context->out_xml_str, p_context->p_cpi->tmp_buff_xml, max_size); output_condition_success_end(p_context); } } /*! handle HWVR query */ else if(strncmp(type, "hwvr", strlen("hwvr")) == 0) { uint8_t hardware_version[CPI_HARDWARE_VERSION_SIZE] = { 0 }; ret = cpi_get_hardware_version_data(p_context->p_cpi, hardware_version); if(CPI_FAILED(ret)) { output_condition_failure(p_context, type, ret); } else { /*! blank out temporary buffer */ strcpy(p_context->p_cpi->tmp_buff_xml, ""); /*! convert serial number to string format */ { char buff[8]; int v; for(v=0;v<CPI_HARDWARE_VERSION_SIZE;v++) { sprintf(buff, "%.02X", (uint32_t)hardware_version[v]); strncat(p_context->p_cpi->tmp_buff_xml, buff, max_size); } } output_condition_success_beg(p_context, type); strncat(p_context->out_xml_str, p_context->p_cpi->tmp_buff_xml, max_size); output_condition_success_end(p_context); } } /*! handle CHAL query */ else if(strncmp(type, "chal", strlen("chal")) == 0) { uint16_t key_id = 0; uint8_t rand_data[CPI_RNDX_SIZE] = { 0 }; /*! retrieve key_id */ { ret = get_attr_uint16(attr, "key_id", &key_id); if(CPI_FAILED(ret)) { return ret; } } /*! parse random data input */ { const char *rand_data_str = 0; ret = get_attr_str(attr, "rand_data", (char const **)&rand_data_str); if(CPI_FAILED(ret)) { return ret; } /*! handle invalid # of characters */ if(strlen(rand_data_str) < (CPI_RNDX_SIZE*2)) { return CPI_FAIL; } int v; for(v=0;v<CPI_RNDX_SIZE;v++) { uint32_t cur_val = 0; ret = sscanf(&rand_data_str[v*2], "%02X", &cur_val); if(ret != 1) { return CPI_FAIL; } rand_data[v] = (uint8_t)cur_val; } } uint8_t *result1 = (uint8_t*)&p_context->p_cpi->tmp_buff_xml[0]; uint8_t *result2 = (uint8_t*)&p_context->p_cpi->tmp_buff_xml[CPI_RESULT1_SIZE]; uint8_t *result3 = (uint8_t*)&p_context->p_cpi->tmp_buff_xml[CPI_RESULT1_SIZE + CPI_RESULT2_SIZE]; /*! clear result buffers */ memset(result1, 0, CPI_RESULT1_SIZE); memset(result2, 0, CPI_RESULT2_SIZE); memset(result3, 0, CPI_RESULT3_SIZE); ret = cpi_issue_challenge(p_context->p_cpi, key_id, rand_data, result1, result2, result3); if(CPI_FAILED(ret)) { output_condition_failure(p_context, type, ret); } else { output_condition_success_beg(p_context, type); strncat(p_context->out_xml_str, "\n", max_size); strncat(p_context->out_xml_str, " <enc_owner_key>", max_size); /*! convert result1 to string format */ { char buff[8]; int v; for(v=0;v<CPI_RESULT1_SIZE;v++) { sprintf(buff, "%.02X", (uint32_t)result1[v]); strncat(p_context->out_xml_str, buff, max_size); if(v == (CPI_RESULT1_ENC_OK_SIZE-1)) { strncat(p_context->out_xml_str, "</enc_owner_key>\n", max_size); strncat(p_context->out_xml_str, " <rand_data>", max_size); } else if(v == (CPI_RESULT1_ENC_OK_SIZE+CPI_RESULT1_RAND_SIZE-1)) { strncat(p_context->out_xml_str, "</rand_data>\n", max_size); strncat(p_context->out_xml_str, " <vers>", max_size); } else if(v == (CPI_RESULT1_SIZE-1)) { strncat(p_context->out_xml_str, "</vers>\n", max_size); } } } strncat(p_context->out_xml_str, " <signature>", max_size); /*! convert result2 to string format */ { char buff[8]; int v; for(v=0;v<CPI_RESULT2_SIZE;v++) { sprintf(buff, "%.02X", (uint32_t)result2[v]); strncat(p_context->out_xml_str, buff, max_size); } } #if defined(CNPLATFORM_falconwing) { char buff[8]; int v; for(v=0;v<CPI_RESULT3_SIZE;v++) { sprintf(buff, "%.02X", (uint32_t)result3[v]); strncat(p_context->out_xml_str, buff, max_size); } } #endif strncat(p_context->out_xml_str, "</signature>\n", max_size); strncat(p_context->out_xml_str, " ", max_size); output_condition_success_end(p_context); } } /*! handle unknown query */ else { strncat(p_context->out_xml_str, " <response result=\"failure\">Unknown \"type\" value</response>\n", max_size); } return CPI_OK; }