/* * hardware.c - various hardware probing functionality * * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. * All rights reserved. * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program. If not, see . * * Author(s): Erik Troan * Matt Wilson * Michael Fulbright * Jeremy Katz */ #include #include #include #include #include #include #include #include #include #include "loader.h" #include "hardware.h" /* FIXME: for turning off dma */ #include #include #include "../isys/isys.h" #include "../isys/log.h" /* boot flags */ extern uint64_t flags; static int detectHardware() { int child, rc, status; int timeout = 0; /* FIXME: commandline option for this */ fprintf(stderr, "detecting hardware...\n"); logMessage(DEBUGLVL, "probing buses"); if (!(child = fork())) { int fd = open("/dev/tty3", O_RDWR); dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); close(fd); rc = execl("/sbin/udevadm", "udevadm", "trigger", NULL); _exit(1); } waitpid(child, &status, 0); if (!WIFEXITED(status) || (WIFEXITED(status) && WEXITSTATUS(status))) { rc = 1; } else { rc = 0; } fprintf(stderr, "waiting for hardware to initialize...\n"); logMessage(DEBUGLVL, "waiting for hardware to initialize"); if (!(child = fork())) { char *args[] = { "/sbin/udevadm", "settle", NULL, NULL }; int fd = open("/dev/tty3", O_RDWR); dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); close(fd); if (timeout) { checked_asprintf(&args[2], "--timeout=%d", timeout); } rc = execv("/sbin/udevadm", args); _exit(1); } waitpid(child, &status, 0); if (!WIFEXITED(status) || (WIFEXITED(status) && WEXITSTATUS(status))) { rc = 1; } else { rc = 0; } if (rc) { return LOADER_ERROR; } return LOADER_OK; } /* this allows us to do an early load of modules specified on the * command line to allow automating the load order of modules so that * eg, certain scsi controllers are definitely first. * FIXME: this syntax is likely to change in a future release * but is done as a quick hack for the present. */ int earlyModuleLoad(int justProbe) { int fd, len, i; char buf[1024], *cmdLine; gint argc = 0; gchar **argv = NULL; GError *optErr = NULL; /* FIXME: reparsing /proc/cmdline to avoid major loader changes. * should probably be done in loader.c:parseCmdline() like everything * else */ if ((fd = open("/proc/cmdline", O_RDONLY)) < 0) return 1; len = read(fd, buf, sizeof(buf) - 1); close(fd); if (len <= 0) return 1; buf[len] = '\0'; cmdLine = buf; if (!g_shell_parse_argv(cmdLine, &argc, &argv, &optErr)) { g_error_free(optErr); return 1; } for (i=0; i < argc; i++) { if (!strncasecmp(argv[i], "driverload=", 11)) { logMessage(INFO, "loading %s early", argv[i] + 11); mlLoadModuleSet(argv[i] + 11); } } return 0; } int busProbe(int justProbe) { /* autodetect whatever we can */ if (justProbe) return 0; return detectHardware(); }