11553Srgrimes/* 21553Srgrimes * Copyright 2007-2014, Ingo Weinhold, ingo_weinhold@gmx.de. 31553Srgrimes * Copyright 2002-2010, Axel D��rfler, axeld@pinc-software.de. 41553Srgrimes * Distributed under the terms of the MIT License. 51553Srgrimes * 61553Srgrimes * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 71553Srgrimes * Distributed under the terms of the NewOS License. 81553Srgrimes */ 91553Srgrimes 101553Srgrimes 111553Srgrimes#include "vfs_boot.h" 121553Srgrimes 131553Srgrimes#include <stdio.h> 141553Srgrimes#include <strings.h> 151553Srgrimes 161553Srgrimes#include <fs_info.h> 171553Srgrimes#include <OS.h> 181553Srgrimes 191553Srgrimes#include <boot/kernel_args.h> 201553Srgrimes#include <directories.h> 211553Srgrimes#include <disk_device_manager/KDiskDevice.h> 221553Srgrimes#include <disk_device_manager/KDiskDeviceManager.h> 231553Srgrimes#include <disk_device_manager/KPartitionVisitor.h> 241553Srgrimes#include <DiskDeviceTypes.h> 251553Srgrimes#include <file_cache.h> 261553Srgrimes#include <fs/KPath.h> 271553Srgrimes#include <kmodule.h> 281553Srgrimes#include <syscalls.h> 291553Srgrimes#include <util/KMessage.h> 30114601Sobrien#include <util/Stack.h> 311553Srgrimes#include <vfs.h> 3230260Scharnier 331553Srgrimes#include "vfs_net_boot.h" 341553Srgrimes 351553Srgrimes 361553Srgrimes//#define TRACE_VFS 371553Srgrimes#ifdef TRACE_VFS 381553Srgrimes# define TRACE(x) dprintf x 39114601Sobrien#else 4030260Scharnier# define TRACE(x) ; 41146755Scharnier#endif 42114601Sobrien 43114601Sobrien 441553Srgrimestypedef Stack<KPartition *> PartitionStack; 451553Srgrimes 46142832Srustatic struct { 471553Srgrimes const char *path; 48113596Snectar const char *target; 491553Srgrimes} sPredefinedLinks[] = { 501553Srgrimes { kGlobalSystemDirectory, kSystemDirectory }, 511553Srgrimes { kGlobalBinDirectory, kSystemBinDirectory }, 521553Srgrimes { kGlobalEtcDirectory, kSystemEtcDirectory }, 531553Srgrimes { kGlobalTempDirectory, kSystemTempDirectory }, 54285205Sgarga { kGlobalVarDirectory, kSystemVarDirectory }, 551553Srgrimes { kGlobalPackageLinksDirectory, kSystemPackageLinksDirectory }, 561553Srgrimes {NULL} 571553Srgrimes}; 581553Srgrimes 591553Srgrimes// This can be used by other code to see if there is a boot file system already 601553Srgrimesdev_t gBootDevice = -1; 611553Srgrimesbool gReadOnlyBootDevice = false; 621553Srgrimes 631553Srgrimes 641553Srgrimes/*! No image was chosen - prefer disks with names like "Haiku", or "System" 651553Srgrimes */ 661553Srgrimesint 671553Srgrimescompare_image_boot(const void* _a, const void* _b) 681553Srgrimes{ 69113666Snectar KPartition* a = *(KPartition**)_a; 70113666Snectar KPartition* b = *(KPartition**)_b; 711553Srgrimes 72227257Sed if (a->ContentName() != NULL) { 731553Srgrimes if (b->ContentName() == NULL) 741553Srgrimes return 1; 751553Srgrimes } else if (b->ContentName() != NULL) { 761553Srgrimes return -1; 771553Srgrimes } else 78142832Sru return 0; 791553Srgrimes 801553Srgrimes int compare = strcasecmp(a->ContentName(), b->ContentName()); 811553Srgrimes if (!compare) 821553Srgrimes return 0; 831553Srgrimes 842551Sgpalmer if (!strcasecmp(a->ContentName(), "Haiku")) 851553Srgrimes return 1; 8639777Sdt if (!strcasecmp(b->ContentName(), "Haiku")) 8723517Swosch return -1; 8823517Swosch if (!strncmp(a->ContentName(), "System", 6)) 8999819Salfred return 1; 9099819Salfred if (!strncmp(b->ContentName(), "System", 6)) 9199819Salfred return -1; 9299819Salfred 9399819Salfred return compare; 9499819Salfred} 951553Srgrimes 961553Srgrimes 9799819Salfred/*! The system was booted from CD - prefer CDs over other entries. If there 981553Srgrimes is no CD, fall back to the standard mechanism (as implemented by 99113596Snectar compare_image_boot(). 100113596Snectar*/ 10116876Sguidostatic int 10216876Sguidocompare_cd_boot(const void* _a, const void* _b) 1031553Srgrimes{ 1041553Srgrimes KPartition* a = *(KPartition**)_a; 10599819Salfred KPartition* b = *(KPartition**)_b; 10699819Salfred 107113596Snectar bool aIsCD = a->Type() != NULL 10899819Salfred && !strcmp(a->Type(), kPartitionTypeDataSession); 10999819Salfred bool bIsCD = b->Type() != NULL 1101553Srgrimes && !strcmp(b->Type(), kPartitionTypeDataSession); 11116876Sguido 1122551Sgpalmer int compare = (int)aIsCD - (int)bIsCD; 11316876Sguido if (compare != 0) 11416876Sguido return compare; 11516876Sguido 116132509Simp return compare_image_boot(_a, _b); 11741712Sdillon} 1181553Srgrimes 119132509Simp 1202551Sgpalmer/*! Computes a check sum for the specified block. 1211553Srgrimes The check sum is the sum of all data in that block interpreted as an 12216876Sguido array of uint32 values. 123146755Scharnier Note, this must use the same method as the one used in 124142832Sru boot/platform/bios_ia32/devices.cpp (or similar solutions). 1251553Srgrimes*/ 126142832Srustatic uint32 127142832Srucompute_check_sum(KDiskDevice* device, off_t offset) 128142832Sru{ 12932397Swosch char buffer[512]; 13032397Swosch ssize_t bytesRead = read_pos(device->FD(), offset, buffer, sizeof(buffer)); 13117672Swosch if (bytesRead < B_OK) 132142832Sru return 0; 133142832Sru 134142832Sru if (bytesRead < (ssize_t)sizeof(buffer)) 135132507Simp memset(buffer + bytesRead, 0, sizeof(buffer) - bytesRead); 136132507Simp 137132507Simp uint32* array = (uint32*)buffer; 1382551Sgpalmer uint32 sum = 0; 139132509Simp 140132507Simp for (uint32 i = 0; 1412551Sgpalmer i < (bytesRead + sizeof(uint32) - 1) / sizeof(uint32); i++) { 142132509Simp sum += array[i]; 143132509Simp } 144132509Simp 1451553Srgrimes return sum; 1461553Srgrimes} 1471553Srgrimes 14835286Sphk 14935286Sphk// #pragma mark - BootMethod 15035286Sphk 15116876Sguido 15216876SguidoBootMethod::BootMethod(const KMessage& bootVolume, int32 method) 15316876Sguido : 1542551Sgpalmer fBootVolume(bootVolume), 1551553Srgrimes fMethod(method) 1561553Srgrimes{ 1571553Srgrimes} 1581553Srgrimes 1591553Srgrimes 1601553SrgrimesBootMethod::~BootMethod() 1611553Srgrimes{ 16216946Smartin} 1631553Srgrimes 1641553Srgrimes 1651553Srgrimesstatus_t 1661553SrgrimesBootMethod::Init() 1671553Srgrimes{ 1681553Srgrimes return B_OK; 1691553Srgrimes} 1701553Srgrimes 1711553Srgrimes 1721553Srgrimes// #pragma mark - DiskBootMethod 1731553Srgrimes 1741553Srgrimes 1751553Srgrimesclass DiskBootMethod : public BootMethod { 1761553Srgrimespublic: 1771553Srgrimes DiskBootMethod(const KMessage& bootVolume, int32 method) 1781553Srgrimes : BootMethod(bootVolume, method) 1791553Srgrimes { 1801553Srgrimes } 1811553Srgrimes 18241712Sdillon virtual bool IsBootDevice(KDiskDevice* device, bool strict); 18341712Sdillon virtual bool IsBootPartition(KPartition* partition, bool& foundForSure); 18441712Sdillon virtual void SortPartitions(KPartition** partitions, int32 count); 18541712Sdillon}; 18641712Sdillon 18741712Sdillon 18841712Sdillonbool 18941712SdillonDiskBootMethod::IsBootDevice(KDiskDevice* device, bool strict) 19041712Sdillon{ 19141712Sdillon disk_identifier* disk; 19241712Sdillon int32 diskIdentifierSize; 19341712Sdillon if (fBootVolume.FindData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE, 19441712Sdillon (const void**)&disk, &diskIdentifierSize) != B_OK) { 19541712Sdillon dprintf("DiskBootMethod::IsBootDevice(): no disk identifier!\n"); 196132509Simp return false; 19741712Sdillon } 19841712Sdillon 19941712Sdillon TRACE(("boot device: bus %" B_PRId32 ", device %" B_PRId32 "\n", 20041712Sdillon disk->bus_type, disk->device_type)); 20141712Sdillon 20241712Sdillon // Assume that CD boots only happen off removable media. 20341712Sdillon if (fMethod == BOOT_METHOD_CD && !device->IsRemovable()) 20441712Sdillon return false; 20541712Sdillon 20617672Swosch switch (disk->bus_type) { 20732397Swosch case PCI_BUS: 208192432Sbrian case LEGACY_BUS: 209192432Sbrian // TODO: implement this! (and then enable this feature in the boot 210192432Sbrian // loader) 211192432Sbrian // (we need a way to get the device_node of a device, then) 212192432Sbrian break; 21317672Swosch 21417672Swosch case UNKNOWN_BUS: 21517672Swosch // nothing to do here 2161553Srgrimes break; 2172551Sgpalmer } 21816876Sguido 21917125Sbde switch (disk->device_type) { 220114159Snectar case UNKNOWN_DEVICE: 221114159Snectar // test if the size of the device matches 22216876Sguido // (the BIOS might have given us the wrong value here, though) 22316876Sguido if (strict && device->Size() != disk->device.unknown.size) 2241553Srgrimes return false; 22516876Sguido 22616876Sguido // Skip the check sum test for CDs, since we didn't read anything 22716876Sguido // useful from the disk in the boot loader. 228296424Sdwmalone if (fMethod == BOOT_METHOD_CD) 22916876Sguido break; 23016876Sguido 23116876Sguido // check if the check sums match, too 23216876Sguido for (int32 i = 0; i < NUM_DISK_CHECK_SUMS; i++) { 23316876Sguido if (disk->device.unknown.check_sums[i].offset == -1) 23416876Sguido continue; 235296424Sdwmalone 23616876Sguido if (compute_check_sum(device, 23716876Sguido disk->device.unknown.check_sums[i].offset) 23816876Sguido != disk->device.unknown.check_sums[i].sum) { 23916876Sguido return false; 24016876Sguido } 24116876Sguido } 24216876Sguido break; 24316876Sguido 24416876Sguido case ATA_DEVICE: 24516876Sguido case ATAPI_DEVICE: 24616876Sguido case SCSI_DEVICE: 247114159Snectar case USB_DEVICE: 248114159Snectar case FIREWIRE_DEVICE: 249114159Snectar case FIBRE_DEVICE: 250114159Snectar // TODO: implement me! 251114159Snectar break; 252114159Snectar } 253114159Snectar 254114159Snectar return true; 25516876Sguido} 25616876Sguido 25716876Sguido 25816876Sguidobool 25916876SguidoDiskBootMethod::IsBootPartition(KPartition* partition, bool& foundForSure) 26016876Sguido{ 26116876Sguido off_t bootPartitionOffset = fBootVolume.GetInt64( 26216876Sguido BOOT_VOLUME_PARTITION_OFFSET, 0); 26316876Sguido 26416876Sguido if (!fBootVolume.GetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, false)) { 26517125Sbde // the simple case: we can just boot from the selected boot 26617125Sbde // device 26717125Sbde if (partition->Offset() == bootPartitionOffset) { 26817125Sbde dprintf("Identified boot partition by partition offset.\n"); 26916876Sguido foundForSure = true; 270114159Snectar return true; 271114159Snectar } 27216876Sguido } else { 273114159Snectar // For now, unless we can positively identify an anyboot CD, we will 27416876Sguido // just collect all BFS/ISO9660 volumes. 27516876Sguido 27616876Sguido if (fMethod == BOOT_METHOD_CD) { 27717125Sbde // Check for the boot partition of an anyboot CD. We identify it as 27816876Sguido // such if it is a partition on the CD, has type BFS, and the boot 27916876Sguido // partition offset is 0 28016876Sguido KDiskDevice* device = partition->Device(); 28116876Sguido if (IsBootDevice(device, false) 28216876Sguido && bootPartitionOffset == 0 && partition->Parent() == device 28316876Sguido && device->ContentType() != NULL 28416876Sguido && strcmp(device->ContentType(), kPartitionTypeIntel) == 0 28516876Sguido && partition->ContentType() != NULL 28616876Sguido && strcmp(partition->ContentType(), kPartitionTypeBFS) == 0) { 28733413Sguido dprintf("Identified anyboot CD.\n"); 28833413Sguido foundForSure = true; 28916876Sguido return true; 29016876Sguido } 29116876Sguido 292296424Sdwmalone // Ignore non-session partitions, if a boot partition was selected 29316876Sguido // by the user. 29416876Sguido if (fBootVolume.GetBool(BOOT_VOLUME_USER_SELECTED, false) 29516876Sguido && partition->Type() != NULL 29616876Sguido && strcmp(partition->Type(), kPartitionTypeDataSession) != 0) { 29716876Sguido return false; 298296424Sdwmalone } 29916876Sguido } 30016876Sguido 30116876Sguido if (partition->ContentType() != NULL 30216876Sguido && (strcmp(partition->ContentType(), kPartitionTypeBFS) == 0 30316876Sguido || strcmp(partition->ContentType(), kPartitionTypeISO9660) == 0)) { 30416876Sguido return true; 30516876Sguido } 30616876Sguido } 3071553Srgrimes 3081553Srgrimes return false; 3091553Srgrimes} 3101553Srgrimes 3111553Srgrimes 3121553Srgrimesvoid 3131553SrgrimesDiskBootMethod::SortPartitions(KPartition** partitions, int32 count) 3141553Srgrimes{ 3151553Srgrimes qsort(partitions, count, sizeof(KPartition*), 3161553Srgrimes fMethod == BOOT_METHOD_CD ? compare_cd_boot : compare_image_boot); 3171553Srgrimes} 3181553Srgrimes 3191553Srgrimes 3201553Srgrimes// #pragma mark - 3211553Srgrimes 3221553Srgrimes 3231553Srgrimes/*! Make the boot partition (and probably others) available. 3241553Srgrimes The partitions that are a boot candidate a put into the /a partitions 3251553Srgrimes stack. If the user selected a boot device, there is will only be one 3261553Srgrimes entry in this stack; if not, the most likely is put up first. 3271553Srgrimes The boot code should then just try them one by one. 3281553Srgrimes*/ 3291553Srgrimesstatic status_t 3301553Srgrimesget_boot_partitions(KMessage& bootVolume, PartitionStack& partitions) 3311553Srgrimes{ 3321553Srgrimes dprintf("get_boot_partitions(): boot volume message:\n"); 3331553Srgrimes bootVolume.Dump(&dprintf); 3341553Srgrimes 335113596Snectar // create boot method 336113596Snectar int32 bootMethodType = bootVolume.GetInt32(BOOT_METHOD, BOOT_METHOD_DEFAULT); 337113596Snectar dprintf("get_boot_partitions(): boot method type: %" B_PRId32 "\n", 338114159Snectar bootMethodType); 339113596Snectar 340114159Snectar BootMethod* bootMethod = NULL; 341114159Snectar switch (bootMethodType) { 342114159Snectar case BOOT_METHOD_NET: 343114159Snectar bootMethod = new(nothrow) NetBootMethod(bootVolume, bootMethodType); 344114159Snectar break; 345114159Snectar 346114159Snectar case BOOT_METHOD_HARD_DISK: 347114159Snectar case BOOT_METHOD_CD: 348114159Snectar default: 349114159Snectar bootMethod = new(nothrow) DiskBootMethod(bootVolume, 350114159Snectar bootMethodType); 351114159Snectar break; 352114159Snectar } 353114159Snectar 354114159Snectar status_t status = bootMethod != NULL ? bootMethod->Init() : B_NO_MEMORY; 355223818Sgordon if (status != B_OK) 3561553Srgrimes return status; 35716876Sguido 3581553Srgrimes KDiskDeviceManager::CreateDefault(); 3591553Srgrimes KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 36039777Sdt 361223818Sgordon status = manager->InitialDeviceScan(); 3627277Swpaul if (status != B_OK) { 363223818Sgordon dprintf("KDiskDeviceManager::InitialDeviceScan() returned error: %s\n", 364223818Sgordon strerror(status)); 36551025Speter // InitialDeviceScan returns error if one (or more) partitions are 36651025Speter // determined to be invalid. The partition we are trying to boot from 36730260Scharnier // may be usuable anyway, so don't fail here. 368113596Snectar } 369113596Snectar 370113596Snectar#if KDEBUG 371142832Sru // dump devices and partitions 372142832Sru KDiskDevice *device; 373142832Sru int32 cookie = 0; 374142832Sru while ((device = manager->NextDevice(&cookie)) != NULL) { 375142832Sru device->Dump(true, 0); 376142832Sru } 37739777Sdt#endif 37823517Swosch 37916876Sguido struct BootPartitionVisitor : KPartitionVisitor { 38016876Sguido BootPartitionVisitor(BootMethod* bootMethod, PartitionStack &stack) 38116876Sguido : fPartitions(stack), 38216876Sguido fBootMethod(bootMethod) 383113596Snectar { 384113596Snectar } 385113596Snectar 386113596Snectar virtual bool VisitPre(KPartition *partition) 387113596Snectar { 388113596Snectar if (!partition->ContainsFileSystem()) 389113596Snectar return false; 390113596Snectar 391113596Snectar bool foundForSure = false; 392113596Snectar if (fBootMethod->IsBootPartition(partition, foundForSure)) 393113596Snectar fPartitions.Push(partition); 394113596Snectar 395113596Snectar // if found for sure, we can terminate the search 396113596Snectar return foundForSure; 397113596Snectar } 398113596Snectar 399113596Snectar private: 400113596Snectar PartitionStack &fPartitions; 401113596Snectar BootMethod* fBootMethod; 402113596Snectar } visitor(bootMethod, partitions); 403113596Snectar 404113596Snectar bool strict = true; 405113596Snectar 406113596Snectar while (true) { 407113596Snectar KDiskDevice *device; 408113596Snectar int32 cookie = 0; 409113596Snectar while ((device = manager->NextDevice(&cookie)) != NULL) { 410113666Snectar if (!bootMethod->IsBootDevice(device, strict)) 411113596Snectar continue; 412113596Snectar 413113596Snectar if (device->VisitEachDescendant(&visitor) != NULL) 414113596Snectar break; 415113596Snectar } 416113596Snectar 417113596Snectar if (!partitions.IsEmpty() || !strict) 418113666Snectar break; 419113596Snectar 420113596Snectar // we couldn't find any potential boot devices, try again less strict 421113596Snectar strict = false; 422113596Snectar } 423113596Snectar 424113596Snectar // sort partition list (e.g.. when booting from CD, CDs should come first in 425113596Snectar // the list) 426113666Snectar if (!bootVolume.GetBool(BOOT_VOLUME_USER_SELECTED, false)) 427113596Snectar bootMethod->SortPartitions(partitions.Array(), partitions.CountItems()); 428113596Snectar 429113596Snectar return B_OK; 430113596Snectar} 431113596Snectar 432113596Snectar 433113596Snectar// #pragma mark - 434113666Snectar 435113596Snectar 436113596Snectarstatus_t 437113596Snectarvfs_bootstrap_file_systems(void) 438113596Snectar{ 439113596Snectar status_t status; 440113596Snectar 441113596Snectar // bootstrap the root filesystem 442113666Snectar status = _kern_mount("/", NULL, "rootfs", 0, NULL, 0); 443113596Snectar if (status < B_OK) 444113596Snectar panic("error mounting rootfs!\n"); 445113596Snectar 446113596Snectar _kern_setcwd(-1, "/"); 447113596Snectar 448113596Snectar // bootstrap the devfs 449113596Snectar _kern_create_dir(-1, "/dev", 0755); 450113666Snectar status = _kern_mount("/dev", NULL, "devfs", 0, NULL, 0); 451113596Snectar if (status < B_OK) 452113596Snectar panic("error mounting devfs\n"); 453113596Snectar 454113596Snectar // create directory for the boot volume 455113596Snectar _kern_create_dir(-1, "/boot", 0755); 456113596Snectar 457113596Snectar // create some standard links on the rootfs 458113596Snectar 459113666Snectar for (int32 i = 0; sPredefinedLinks[i].path != NULL; i++) { 460113596Snectar _kern_create_symlink(-1, sPredefinedLinks[i].path, 461113596Snectar sPredefinedLinks[i].target, 0777); 462113596Snectar // we don't care if it will succeed or not 463113596Snectar } 464113596Snectar 465113596Snectar return B_OK; 466113596Snectar} 467113596Snectar 468113596Snectar 469113596Snectarvoid 470113596Snectarvfs_mount_boot_file_system(kernel_args* args) 471113596Snectar{ 472113596Snectar KMessage bootVolume; 473142832Sru bootVolume.SetTo(args->boot_volume, args->boot_volume_size); 474142832Sru 475142832Sru PartitionStack partitions; 47616876Sguido status_t status = get_boot_partitions(bootVolume, partitions); 47716876Sguido if (status < B_OK) { 47816876Sguido panic("get_boot_partitions failed!"); 47916876Sguido } 480142832Sru if (partitions.IsEmpty()) { 481142832Sru panic("did not find any boot partitions! @! syslog | tail 15"); 48216876Sguido } 4831553Srgrimes 484113596Snectar dev_t bootDevice = -1; 48516876Sguido 48616876Sguido KPartition* bootPartition; 48716876Sguido while (partitions.Pop(&bootPartition)) { 488142832Sru KPath path; 489142832Sru if (bootPartition->GetPath(&path) != B_OK) 490142832Sru panic("could not get boot device!\n"); 49116876Sguido 49216876Sguido const char* fsName = NULL; 49316876Sguido bool readOnly = false; 49416876Sguido if (strcmp(bootPartition->ContentType(), kPartitionTypeISO9660) == 0) { 495142832Sru fsName = "iso9660:write_overlay:attribute_overlay"; 496142832Sru readOnly = true; 49716876Sguido } else if (bootPartition->IsReadOnly() 4981553Srgrimes && strcmp(bootPartition->ContentType(), kPartitionTypeBFS) == 0) { 49916876Sguido fsName = "bfs:write_overlay"; 500113666Snectar readOnly = true; 50116876Sguido } 50216876Sguido 50316876Sguido TRACE(("trying to mount boot partition: %s\n", path.Path())); 50416876Sguido 50516876Sguido bootDevice = _kern_mount("/boot", path.Path(), fsName, 0, NULL, 0); 5061553Srgrimes if (bootDevice >= 0) { 50716876Sguido dprintf("Mounted boot partition: %s\n", path.Path()); 508113666Snectar gReadOnlyBootDevice = readOnly; 509142832Sru break; 510142832Sru } 511142832Sru } 51216876Sguido 51316876Sguido if (bootDevice < B_OK) 5141553Srgrimes panic("could not mount boot device!\n"); 51516876Sguido 516113666Snectar // create link for the name of the boot device 517142832Sru 518142832Sru fs_info info; 519142832Sru if (_kern_read_fs_info(bootDevice, &info) == B_OK) { 52016876Sguido char path[B_FILE_NAME_LENGTH + 1]; 52116876Sguido snprintf(path, sizeof(path), "/%s", info.volume_name); 52216876Sguido 52316876Sguido _kern_create_symlink(-1, path, "/boot", 0777); 524113666Snectar } 52516876Sguido 52616876Sguido // If we're booting off a packaged system, mount packagefs. 52716876Sguido struct stat st; 52816876Sguido if (bootVolume.GetBool(BOOT_VOLUME_PACKAGED, false) 52916876Sguido || (bootVolume.GetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, false) 53016876Sguido && lstat(kSystemPackagesDirectory, &st) == 0)) { 53116876Sguido static const char* const kPackageFSName = "packagefs"; 532113666Snectar 533142832Sru char arguments[256]; 534142832Sru strlcpy(arguments, "packages /boot/system/packages; type system", 535142832Sru sizeof(arguments)); 53616876Sguido if (const char* stateName 5377257Swpaul = bootVolume.GetString(BOOT_VOLUME_PACKAGES_STATE, NULL)) { 53816876Sguido strlcat(arguments, "; state ", sizeof(arguments)); 53916876Sguido strlcat(arguments, stateName, sizeof(arguments)); 540113666Snectar } 541142832Sru 542142832Sru dev_t packageMount = _kern_mount("/boot/system", NULL, kPackageFSName, 543142832Sru 0, arguments, 0 /* unused argument length */); 54416876Sguido if (packageMount < 0) { 54516876Sguido panic("Failed to mount system packagefs: %s", 54616876Sguido strerror(packageMount)); 54716876Sguido } 54816876Sguido 549113666Snectar packageMount = _kern_mount("/boot/home/config", NULL, kPackageFSName, 0, 550142832Sru "packages /boot/home/config/packages; type home", 551142832Sru 0 /* unused argument length */); 552142832Sru if (packageMount < 0) { 55316876Sguido dprintf("Failed to mount home packagefs: %s\n", 55416876Sguido strerror(packageMount)); 55516876Sguido } 55616876Sguido } 55716876Sguido 5587257Swpaul status = _kern_mount("/boot/system/var/shared_memory", NULL, "ramfs", 0, NULL, 0); 5591553Srgrimes if (status < B_OK) 56039777Sdt dprintf("Failed to mount shared memory FS: %s\n", strerror(status)); 56133434Sguido 56233413Sguido // Now that packagefs is mounted, the boot volume is really ready. 56333614Sguido gBootDevice = bootDevice; 56419085Swpaul 56519085Swpaul // Do post-boot-volume module initialization. The module code wants to know 56619085Swpaul // whether the module images the boot loader has pre-loaded are the same as 56757868Spaul // on the boot volume. That is the case when booting from hard disk or CD, 56857868Spaul // but not via network. 56919085Swpaul int32 bootMethodType = bootVolume.GetInt32(BOOT_METHOD, BOOT_METHOD_DEFAULT); 57033413Sguido bool bootingFromBootLoaderVolume = bootMethodType == BOOT_METHOD_HARD_DISK 57119085Swpaul || bootMethodType == BOOT_METHOD_CD; 57219085Swpaul module_init_post_boot_device(bootingFromBootLoaderVolume); 57333434Sguido 57433413Sguido file_cache_init_post_boot_device(); 57519085Swpaul 5761553Srgrimes // search for other disk systems 5772916Swollman KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 57817125Sbde manager->RescanDiskSystems(); 5792934Swollman manager->StartMonitoring(); 5802934Swollman} 5812916Swollman 582113666Snectar