status_t device_node::_RegisterDynamic(device_node* previous) { // If this is not a bus, we don't have to scan it if (find_attr(this, B_DEVICE_BUS, false, B_STRING_TYPE) == NULL) return B_OK; // If we're not being probed, we honour the B_FIND_CHILD_ON_DEMAND // requirements if (!IsProbed() && (fFlags & B_FIND_CHILD_ON_DEMAND) != 0 && !_AlwaysRegisterDynamic()) return B_OK; KPath path; if ((fFlags & B_FIND_MULTIPLE_CHILDREN) == 0) { // find the one driver driver_module_info* bestDriver = NULL; float bestSupport = 0.0; void* cookie = NULL; while (_GetNextDriverPath(cookie, path) == B_OK) { _FindBestDriver(path.Path(), bestDriver, bestSupport, previous); } if (bestDriver != NULL) { TRACE((" register best module \"%s\", support %f\n", bestDriver->info.name, bestSupport)); if (bestDriver->register_device(this) == B_OK) { // There can only be one node of this driver // (usually only one at all, but there might be a new driver // "waiting" for its turn) device_node* child = FindChild(bestDriver->info.name); if (child != NULL) { child->fSupportsParent = bestSupport; if (previous != NULL) { previous->fFlags |= NODE_FLAG_OBSOLETE_DRIVER; previous->Release(); child->fFlags |= NODE_FLAG_WAITING_FOR_DRIVER; } } // TODO: if this fails, we could try the second best driver, // and so on... } put_module(bestDriver->info.name); } } else { // register all drivers that match void* cookie = NULL; while (_GetNextDriverPath(cookie, path) == B_OK) { _RegisterPath(path.Path()); } } return B_OK; }
status_t PackageSettings::Load(dev_t mountPointDeviceID, ino_t mountPointNodeID, PackageFSMountType mountType) { status_t error = fPackageItems.Init(); if (error != B_OK) RETURN_ERROR(error); // get the mount point relative settings file path const char* settingsFilePath = mountType == PACKAGE_FS_MOUNT_TYPE_HOME ? kUserSettingsGlobalDirectory "/packages" + strlen(kUserConfigDirectory) + 1 : kSystemSettingsDirectory "/packages" + strlen(kSystemDirectory) + 1; // get an absolute path KPath path; if (path.InitCheck() != B_OK) RETURN_ERROR(path.InitCheck()); error = vfs_entry_ref_to_path(mountPointDeviceID, mountPointNodeID, NULL, true, path.LockBuffer(), path.BufferSize()); if (error != B_OK) return error; path.UnlockBuffer(); error = path.Append(settingsFilePath); if (error != B_OK) return error; // load the driver settings void* settingsHandle = load_driver_settings(path.Path()); if (settingsHandle == NULL) return B_ENTRY_NOT_FOUND; CObjectDeleter<void, status_t> settingsDeleter(settingsHandle, &unload_driver_settings); const driver_settings* settings = get_driver_settings(settingsHandle); for (int i = 0; i < settings->parameter_count; i++) { const driver_parameter& parameter = settings->parameters[i]; if (strcmp(parameter.name, "Package") != 0 || parameter.value_count < 1) { continue; } error = _AddPackageSettingsItem(parameter); // abort only in case of serious issues (memory shortage) if (error == B_NO_MEMORY) return error; } return B_OK; }
status_t device_node::_AddPath(Stack<KPath*>& stack, const char* basePath, const char* subPath) { KPath* path = new(std::nothrow) KPath; if (path == NULL) return B_NO_MEMORY; status_t status = path->SetTo(basePath); if (status == B_OK && subPath != NULL && subPath[0]) status = path->Append(subPath); if (status == B_OK) status = stack.Push(path); TRACE((" add path: \"%s\", %" B_PRId32 "\n", path->Path(), status)); if (status != B_OK) delete path; return status; }
status_t PackagesDirectory::_Init(struct vnode* vnode, struct stat& _st) { fDirFD = vfs_open_vnode(vnode, O_RDONLY, true); if (fDirFD < 0) { ERROR("Failed to open packages directory \"%s\"\n", strerror(fDirFD)); vfs_put_vnode(vnode); RETURN_ERROR(fDirFD); } // Our vnode reference has been transferred to the FD. // Is it a directory at all? struct stat& st = _st; if (fstat(fDirFD, &st) < 0) RETURN_ERROR(errno); fNodeRef.device = st.st_dev; fNodeRef.node = st.st_ino; // get a normalized path KPath normalizedPath; if (normalizedPath.InitCheck() != B_OK) RETURN_ERROR(normalizedPath.InitCheck()); char* normalizedPathBuffer = normalizedPath.LockBuffer(); status_t error = vfs_entry_ref_to_path(fNodeRef.device, fNodeRef.node, NULL, true, normalizedPathBuffer, normalizedPath.BufferSize()); if (error != B_OK) RETURN_ERROR(error); fPath = strdup(normalizedPathBuffer); if (fPath == NULL) RETURN_ERROR(B_NO_MEMORY); return B_OK; }
// SetTo status_t KFileDiskDevice::SetTo(const char *filePath, const char *devicePath) { // check params if (!filePath || strlen(filePath) > B_PATH_NAME_LENGTH || (devicePath && strlen(devicePath) > B_PATH_NAME_LENGTH)) { return B_BAD_VALUE; } // normalize the file path // (should actually not be necessary, since this method is only invoked // by the DDM, which has already normalized the path) KPath tmpFilePath; status_t error = tmpFilePath.SetTo(filePath, true); if (error != B_OK) return error; // check the file struct stat st; if (stat(filePath, &st) != 0) return errno; if (!S_ISREG(st.st_mode)) return B_BAD_VALUE; // create the device, if requested KPath tmpDevicePath; if (!devicePath) { // no device path: we shall create a new device entry if (tmpDevicePath.InitCheck() != B_OK) return tmpDevicePath.InitCheck(); // TODO: Cleanup. The directory creation is done automatically by the devfs. // // make the file devices dir // if (mkdir(kFileDevicesDir, 0777) != 0) { // if (errno != B_FILE_EXISTS) // return errno; // } // make the directory status_t error = _GetDirectoryPath(ID(), &tmpDevicePath); if (error != B_OK) return error; // if (mkdir(tmpDevicePath.Path(), 0777) != 0) // return errno; // get the device path name error = tmpDevicePath.Append("raw"); if (error != B_OK) return error; devicePath = tmpDevicePath.Path(); // register the file as virtual disk device error = _RegisterDevice(filePath, devicePath); if (error != B_OK) return error; } error = set_string(fFilePath, filePath); if (error != B_OK) return error; error = KDiskDevice::SetTo(devicePath); if (error != B_OK) return error; // reset the B_DISK_DEVICE_IS_FILE flag -- KDiskDevice::SetTo() has cleared // it SetDeviceFlags(DeviceFlags() | B_DISK_DEVICE_IS_FILE); return B_OK; }
static int32 main2(void *unused) { (void)(unused); TRACE("start of main2: initializing devices\n"); boot_splash_init(sKernelArgs.boot_splash); commpage_init_post_cpus(); TRACE("init ports\n"); port_init(&sKernelArgs); TRACE("init user mutex\n"); user_mutex_init(); TRACE("Init modules\n"); boot_splash_set_stage(BOOT_SPLASH_STAGE_1_INIT_MODULES); module_init_post_threads(); // init userland debugging TRACE("Init Userland debugging\n"); init_user_debug(); // init the messaging service TRACE("Init Messaging Service\n"); init_messaging_service(); /* bootstrap all the filesystems */ TRACE("Bootstrap file systems\n"); boot_splash_set_stage(BOOT_SPLASH_STAGE_2_BOOTSTRAP_FS); vfs_bootstrap_file_systems(); TRACE("Init Device Manager\n"); boot_splash_set_stage(BOOT_SPLASH_STAGE_3_INIT_DEVICES); device_manager_init(&sKernelArgs); TRACE("Add preloaded old-style drivers\n"); legacy_driver_add_preloaded(&sKernelArgs); int_init_post_device_manager(&sKernelArgs); TRACE("Mount boot file system\n"); boot_splash_set_stage(BOOT_SPLASH_STAGE_4_MOUNT_BOOT_FS); vfs_mount_boot_file_system(&sKernelArgs); #if ENABLE_SWAP_SUPPORT TRACE("swap_init_post_modules\n"); swap_init_post_modules(); #endif // CPU specific modules may now be available boot_splash_set_stage(BOOT_SPLASH_STAGE_5_INIT_CPU_MODULES); cpu_init_post_modules(&sKernelArgs); TRACE("vm_init_post_modules\n"); boot_splash_set_stage(BOOT_SPLASH_STAGE_6_INIT_VM_MODULES); vm_init_post_modules(&sKernelArgs); TRACE("debug_init_post_modules\n"); debug_init_post_modules(&sKernelArgs); TRACE("device_manager_init_post_modules\n"); device_manager_init_post_modules(&sKernelArgs); boot_splash_set_stage(BOOT_SPLASH_STAGE_7_RUN_BOOT_SCRIPT); boot_splash_uninit(); // NOTE: We could introduce a syscall to draw more icons indicating // stages in the boot script itself. Then we should not free the image. // In that case we should copy it over to the kernel heap, so that we // can still free the kernel args. // The boot splash screen is the last user of the kernel args. // Note: don't confuse the kernel_args structure (which is never freed) // with the kernel args ranges it contains (and which are freed here). vm_free_kernel_args(&sKernelArgs); // start the init process { KPath bootScriptPath; status_t status = find_directory(B_BEOS_SYSTEM_DIRECTORY, gBootDevice, false, bootScriptPath.LockBuffer(), bootScriptPath.BufferSize()); if (status != B_OK) dprintf("main2: find_directory() failed: %s\n", strerror(status)); bootScriptPath.UnlockBuffer(); status = bootScriptPath.Append("boot/Bootscript"); if (status != B_OK) { dprintf("main2: constructing path to Bootscript failed: " "%s\n", strerror(status)); } const char *args[] = { "/bin/sh", bootScriptPath.Path(), NULL }; int32 argc = 2; thread_id thread; thread = load_image(argc, args, NULL); if (thread >= B_OK) { resume_thread(thread); TRACE("Bootscript started\n"); } else dprintf("error starting \"%s\" error = %ld \n", args[0], thread); } return 0; }
void vfs_mount_boot_file_system(kernel_args* args) { PartitionStack partitions; status_t status = get_boot_partitions(args, partitions); if (status < B_OK) { panic("get_boot_partitions failed!"); } if (partitions.IsEmpty()) { panic("did not find any boot partitions!"); } KPartition* bootPartition; while (partitions.Pop(&bootPartition)) { KPath path; if (bootPartition->GetPath(&path) != B_OK) panic("could not get boot device!\n"); const char* fsName = NULL; bool readOnly = false; if (strcmp(bootPartition->ContentType(), "ISO9660 File System") == 0) { fsName = "iso9660:write_overlay:attribute_overlay"; readOnly = true; } else if (bootPartition->IsReadOnly() && strcmp(bootPartition->ContentType(), "Be File System") == 0) { fsName = "bfs:write_overlay"; readOnly = true; } TRACE(("trying to mount boot partition: %s\n", path.Path())); gBootDevice = _kern_mount("/boot", path.Path(), fsName, 0, NULL, 0); if (gBootDevice >= B_OK) { gReadOnlyBootDevice = readOnly; break; } } if (gBootDevice < B_OK) panic("could not mount boot device!\n"); // create link for the name of the boot device fs_info info; if (_kern_read_fs_info(gBootDevice, &info) == B_OK) { char path[B_FILE_NAME_LENGTH + 1]; snprintf(path, sizeof(path), "/%s", info.volume_name); _kern_create_symlink(-1, path, "/boot", 0); } // Do post-boot-volume module initialization. The module code wants to know // whether the module images the boot loader has pre-loaded are the same as // on the boot volume. That is the case when booting from hard disk or CD, // but not via network. int32 bootMethodType = args->boot_volume.GetInt32(BOOT_METHOD, BOOT_METHOD_DEFAULT); bool bootingFromBootLoaderVolume = bootMethodType == BOOT_METHOD_HARD_DISK || bootMethodType == BOOT_METHOD_CD; module_init_post_boot_device(bootingFromBootLoaderVolume); file_cache_init_post_boot_device(); // search for other disk systems KDiskDeviceManager *manager = KDiskDeviceManager::Default(); manager->RescanDiskSystems(); manager->StartMonitoring(); }
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; }