* Copyright 2003-2007, Axel DΓΆrfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#include "Handle.h"
#include <boot/platform.h>
#include <util/kernel_cpp.h>
#include <unistd.h>
#include <errno.h>
#include <dirent.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
extern int __libc_argc;
extern char **__libc_argv;
extern const char *__progname;
extern bool gShowMenu;
static status_t
get_device(const char *path, Node **_device)
{
Handle *device = new Handle(path);
if (device == NULL)
return B_NO_MEMORY;
if (device->InitCheck() != B_OK) {
fprintf(stderr, "%s: Could not open image \"%s\": %s\n",
__progname, path, strerror(device->InitCheck()));
delete device;
return B_ERROR;
}
*_device = device;
return B_OK;
}
static status_t
add_device(const char *path, NodeList *list)
{
Node *device;
status_t status = get_device(path, &device);
if (status < B_OK)
return status;
printf("add \"%s\" to list of boot devices\n", path);
list->Add(device);
return B_OK;
}
static status_t
recursive_add_device(const char *path, NodeList *list)
{
DIR *dir = opendir(path);
if (dir == NULL)
return errno;
struct dirent *dirent;
while ((dirent = readdir(dir)) != NULL) {
if (dirent->d_name[0] == '.')
continue;
char nextPath[PATH_MAX];
strcpy(nextPath, path);
strcat(nextPath, "/");
strcat(nextPath, dirent->d_name);
if (!strcmp(dirent->d_name, "raw")
&& add_device(nextPath, list) == B_OK)
continue;
recursive_add_device(nextPath, list);
}
closedir(dir);
return B_OK;
}
static char *
get_next_argument(int32 *cookie, bool options)
{
int32 i = *cookie + 1;
if (i == 1 && !options) {
while (i < __libc_argc && __libc_argv[i][0] == '-')
i++;
}
for (; i < __libc_argc; i++) {
if (options && __libc_argv[i][0] != '-')
return NULL;
*cookie = i;
return __libc_argv[i];
}
return NULL;
}
static char *
get_next_option(int32 *cookie)
{
return get_next_argument(cookie, true);
}
static char *
get_next_device(int32 *cookie)
{
return get_next_argument(cookie, false);
}
status_t
platform_add_boot_device(struct stage2_args *args, NodeList *devicesList)
{
status_t status = B_ERROR;
Node *device;
int32 cookie = 0;
char *path = get_next_device(&cookie);
if (path != NULL)
status = get_device(path, &device);
else
status = get_device("/boot/home/test-file-device", &device);
if (status == B_OK)
devicesList->Add(device);
return status;
}
status_t
platform_get_boot_partitions(struct stage2_args* args, Node* bootDevice,
NodeList *list, NodeList *partitionList)
{
NodeIterator iterator = list->GetIterator();
boot::Partition *partition = NULL;
while ((partition = (boot::Partition *)iterator.Next()) != NULL) {
partitionList->Insert(partition);
return B_OK;
}
return B_ENTRY_NOT_FOUND;
}
status_t
platform_add_block_devices(struct stage2_args *args, NodeList *list)
{
int32 cookie = 0;
if (get_next_device(&cookie) != NULL) {
char *path;
while ((path = get_next_device(&cookie)) != NULL)
add_device(path, list);
}
bool addDevices = true;
bool scsi = true;
char *option;
cookie = 0;
while ((option = get_next_option(&cookie)) != NULL) {
if (!strcmp(option, "--no-devices"))
addDevices = false;
else if (!strcmp(option, "--no-scsi"))
scsi = false;
else if (!strcmp(option, "--menu"))
gShowMenu = true;
else {
fprintf(stderr, "usage: %s [OPTIONS] [image ...]\n"
" --no-devices\tDon't add real devices from /dev/disk\n"
" --no-scsi\tDon't add SCSI devices (might be problematic with some\n"
"\t\tUSB mass storage drivers)\n"
" --menu\tShow boot menu\n", __progname);
exit(0);
}
}
if (addDevices) {
recursive_add_device("/dev/disk/ide", list);
recursive_add_device("/dev/disk/virtual", list);
if (scsi)
recursive_add_device("/dev/disk/scsi", list);
}
return B_OK;
}
status_t
platform_register_boot_device(Node *device)
{
return B_OK;
}