/* device.c - device manager */ /* * VAS_EBOOT -- GRand Unified Bootloader * Copyright (C) 2002,2005,2007,2008,2009 Free Software Foundation, Inc. * * VAS_EBOOT is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * VAS_EBOOT is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VAS_EBOOT. If not, see . */ #include #include #include #include #include #include #include #include #include VasEBoot_net_t (*VasEBoot_net_open) (const char *name) = NULL; VasEBoot_device_t VasEBoot_device_open (const char *name) { VasEBoot_device_t dev = 0; if (! name) { name = VasEBoot_env_get ("root"); if (name == NULL || *name == '\0') { VasEBoot_error (VAS_EBOOT_ERR_BAD_DEVICE, N_("variable `%s' isn't set"), "root"); goto fail; } } dev = VasEBoot_malloc (sizeof (*dev)); if (! dev) goto fail; dev->net = NULL; /* Try to open a disk. */ dev->disk = VasEBoot_disk_open (name); if (dev->disk) return dev; if (VasEBoot_net_open && VasEBoot_errno == VAS_EBOOT_ERR_UNKNOWN_DEVICE) { VasEBoot_errno = VAS_EBOOT_ERR_NONE; dev->net = VasEBoot_net_open (name); } if (dev->net) return dev; fail: VasEBoot_free (dev); return 0; } VasEBoot_err_t VasEBoot_device_close (VasEBoot_device_t device) { if (device == NULL) return VAS_EBOOT_ERR_NONE; if (device->disk) VasEBoot_disk_close (device->disk); if (device->net) { VasEBoot_free (device->net->server); VasEBoot_free (device->net); } VasEBoot_free (device); return VasEBoot_errno; } struct part_ent { struct part_ent *next; char *name; }; /* Context for VasEBoot_device_iterate. */ struct VasEBoot_device_iterate_ctx { VasEBoot_device_iterate_hook_t hook; void *hook_data; struct part_ent *ents; }; /* Helper for VasEBoot_device_iterate. */ static int iterate_partition (VasEBoot_disk_t disk, const VasEBoot_partition_t partition, void *data) { struct VasEBoot_device_iterate_ctx *ctx = data; struct part_ent *p; char *part_name; p = VasEBoot_malloc (sizeof (*p)); if (!p) { return 1; } part_name = VasEBoot_partition_get_name (partition); if (!part_name) { VasEBoot_free (p); return 1; } p->name = VasEBoot_xasprintf ("%s,%s", disk->name, part_name); VasEBoot_free (part_name); if (!p->name) { VasEBoot_free (p); return 1; } p->next = ctx->ents; ctx->ents = p; return 0; } /* Helper for VasEBoot_device_iterate. */ static int iterate_disk (const char *disk_name, void *data) { struct VasEBoot_device_iterate_ctx *ctx = data; VasEBoot_device_t dev; if (ctx->hook (disk_name, ctx->hook_data)) return 1; dev = VasEBoot_device_open (disk_name); if (! dev) { VasEBoot_errno = VAS_EBOOT_ERR_NONE; return 0; } if (dev->disk) { struct part_ent *p; int ret = 0; ctx->ents = NULL; (void) VasEBoot_partition_iterate (dev->disk, iterate_partition, ctx); VasEBoot_device_close (dev); VasEBoot_errno = VAS_EBOOT_ERR_NONE; p = ctx->ents; while (p != NULL) { struct part_ent *next = p->next; if (!ret) ret = ctx->hook (p->name, ctx->hook_data); VasEBoot_free (p->name); VasEBoot_free (p); p = next; } return ret; } VasEBoot_device_close (dev); return 0; } int VasEBoot_device_iterate (VasEBoot_device_iterate_hook_t hook, void *hook_data) { struct VasEBoot_device_iterate_ctx ctx = { hook, hook_data, NULL }; /* Only disk devices are supported at the moment. */ return VasEBoot_disk_dev_iterate (iterate_disk, &ctx); }