404 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			404 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
 | 
						|
 * 
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining a
 | 
						|
 * copy of this software and associated documentation files (the "Software"),
 | 
						|
 * to deal in the Software without restriction, including without limitation
 | 
						|
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
						|
 * and/or sell copies of the Software, and to permit persons to whom the
 | 
						|
 * Software is furnished to do so, subject to the following conditions:
 | 
						|
 * 
 | 
						|
 * The above copyright notice and this permission notice shall be included in
 | 
						|
 * all copies or substantial portions of the Software.
 | 
						|
 *  
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | 
						|
 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | 
						|
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 | 
						|
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
						|
 * SOFTWARE.
 | 
						|
 * 
 | 
						|
 * Except as contained in this notice, the name of Conectiva Linux shall
 | 
						|
 * not be used in advertising or otherwise to promote the sale, use or other
 | 
						|
 * dealings in this Software without prior written authorization from
 | 
						|
 * Conectiva Linux.
 | 
						|
 *
 | 
						|
 * Author: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
 | 
						|
 *
 | 
						|
 * $XFree86: xc/programs/Xserver/hw/xfree86/xf86cfg/loader.c,v 1.20 2003/12/17 17:45:33 dawes Exp $
 | 
						|
 */
 | 
						|
 | 
						|
#include "config.h"
 | 
						|
#include "cards.h"
 | 
						|
#include "options.h"
 | 
						|
#include "loader.h"
 | 
						|
#include "stubs.h"
 | 
						|
#include <X11/Xresource.h>
 | 
						|
#include <X11/Xos.h>
 | 
						|
 | 
						|
#ifdef USE_MODULES
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#if defined(X_POSIX_C_SOURCE)
 | 
						|
#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
 | 
						|
#include <setjmp.h>
 | 
						|
#undef _POSIX_C_SOURCE
 | 
						|
#else
 | 
						|
#include <setjmp.h>
 | 
						|
#endif
 | 
						|
#include <signal.h>
 | 
						|
#include <ctype.h>
 | 
						|
 | 
						|
#include <stdarg.h>
 | 
						|
 | 
						|
#ifndef SIGNALRETURNSINT
 | 
						|
void sig_handler(int);
 | 
						|
#else
 | 
						|
int sig_handler(int);
 | 
						|
#endif	/* SIGNALRETURNSINT */
 | 
						|
 | 
						|
static Bool EnumDatabase(XrmDatabase*, XrmBindingList, XrmQuarkList,
 | 
						|
			 XrmRepresentation*, XrmValue*, XPointer);
 | 
						|
 | 
						|
static sigjmp_buf jmp;
 | 
						|
int signal_caught;
 | 
						|
int error_level;
 | 
						|
char *loaderPath, **loaderList, **ploaderList;
 | 
						|
extern XrmDatabase options_xrm;
 | 
						|
extern int noverify;
 | 
						|
extern ModuleType module_type;
 | 
						|
static OptionInfoPtr option;
 | 
						|
 | 
						|
extern FontModule *font_module;
 | 
						|
extern int numFontModules;
 | 
						|
 | 
						|
char **checkerLegend;
 | 
						|
int *checkerErrors;
 | 
						|
 | 
						|
#ifndef SIGNALRETURNSINT
 | 
						|
void
 | 
						|
#else
 | 
						|
int
 | 
						|
#endif
 | 
						|
sig_handler(int sig)
 | 
						|
{
 | 
						|
    char *str;
 | 
						|
 | 
						|
    switch (sig) {
 | 
						|
	case SIGTRAP:
 | 
						|
	    str = "TRAP";
 | 
						|
	    break;
 | 
						|
	case SIGBUS:
 | 
						|
	    str = "BUS";
 | 
						|
	    break;
 | 
						|
	case SIGSEGV:
 | 
						|
	    str = "SEGV";
 | 
						|
	    break;
 | 
						|
	case SIGILL:
 | 
						|
	    str = "ILL";
 | 
						|
	    break;
 | 
						|
	case SIGFPE:
 | 
						|
	    str = "FPE";
 | 
						|
	    break;
 | 
						|
	default:
 | 
						|
	    str = "???";
 | 
						|
	    break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (signal_caught == 1) {
 | 
						|
	ErrorF("  ERROR I am dead.\n");
 | 
						|
	exit(1);
 | 
						|
    }
 | 
						|
    else if (signal_caught == 2)
 | 
						|
	abort();
 | 
						|
    ++signal_caught;
 | 
						|
    ErrorF("  ERROR SIG%s caught!\n", str);
 | 
						|
    if (!noverify)
 | 
						|
	error_level += 50;
 | 
						|
    siglongjmp(jmp, 1);
 | 
						|
    /*NOTREACHED*/
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
CheckMsg(int code, char *fmt, ...)
 | 
						|
{
 | 
						|
    va_list ap;
 | 
						|
 | 
						|
    ++checkerErrors[code];
 | 
						|
    ErrorF("%3d ", code);
 | 
						|
 | 
						|
    va_start(ap, fmt);
 | 
						|
    VErrorF(fmt, ap);
 | 
						|
    va_end(ap);
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
EnumDatabase(XrmDatabase *db, XrmBindingList bindings, XrmQuarkList quarks,
 | 
						|
	     XrmRepresentation *type, XrmValue *value, XPointer closure)
 | 
						|
{
 | 
						|
    char *res = XrmQuarkToString(quarks[1]);
 | 
						|
 | 
						|
    if (res) {
 | 
						|
	option = module_options->option;
 | 
						|
	while (option->name) {
 | 
						|
	    if (strcasecmp(option->name, res) == 0)
 | 
						|
		return (False);
 | 
						|
	    ++option;
 | 
						|
	}
 | 
						|
	CheckMsg(CHECKER_OPTION_UNUSED,
 | 
						|
		 "WARNING %s.%s is not used\n",
 | 
						|
		 XrmQuarkToString(quarks[0]), res);
 | 
						|
	++error_level;
 | 
						|
    }
 | 
						|
 | 
						|
    return (False);
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
LoaderInitializeOptions(void)
 | 
						|
{
 | 
						|
    static int first = 1;
 | 
						|
    static char *modules = "lib/modules";
 | 
						|
    volatile Bool options_ok = False;
 | 
						|
    char *ptr, query[256];
 | 
						|
    char *ptr2, query2[256];
 | 
						|
    char *type;
 | 
						|
    XrmValue value;
 | 
						|
    XrmQuark names[2];
 | 
						|
    XrmQuark classes[2];
 | 
						|
    volatile int i;
 | 
						|
    static ModuleType module_types[] = {
 | 
						|
	GenericModule, FontRendererModule, InputModule, VideoModule, NullModule
 | 
						|
    };
 | 
						|
 | 
						|
    /* The offset in this vector must match loader.h:enum ModuleType values */
 | 
						|
    static char *module_strs[] = {
 | 
						|
	"Null Module", "Video Module", "Input Module", "Generic Module", "Font Module"
 | 
						|
    };
 | 
						|
 | 
						|
    if (first) {
 | 
						|
	checkerLegend = (char**)
 | 
						|
	    XtCalloc(1, sizeof(char*) * (CHECKER_LAST_MESSAGE + 1));
 | 
						|
	checkerErrors = (int*)
 | 
						|
	    XtCalloc(1, sizeof(int) * (CHECKER_LAST_MESSAGE + 1));
 | 
						|
	xf86cfgLoaderInit();
 | 
						|
	first = 0;
 | 
						|
 | 
						|
	checkerLegend[CHECKER_OPTIONS_FILE_MISSING] =
 | 
						|
	"The Options file, normally /usr/X11R6/lib/X11/Options was not found.\n"
 | 
						|
	"In the sources, it is at xc/programs/Xserver/hw/xfree86/Options.";
 | 
						|
	checkerLegend[CHECKER_OPTION_DESCRIPTION_MISSING] =
 | 
						|
	"No description for the module option. The description should be in\n"
 | 
						|
	"in the Options file, and using the sintax:\n"
 | 
						|
	"Module.Option:	any text describing the option";
 | 
						|
	checkerLegend[CHECKER_LOAD_FAILED] =
 | 
						|
	"Failed to load the module. Usually the loader will print a complete\n"
 | 
						|
	"description for the reason the module was not loaded. Use the -verbose\n"
 | 
						|
	"command line option if it is not printing any messages.";
 | 
						|
	checkerLegend[CHECKER_RECOGNIZED_AS] =
 | 
						|
	"This message means the module code did not follow what was expected\n"
 | 
						|
	"by the checker. For video drivers, it did not call xf86AddDriver,\n"
 | 
						|
	"a input module did not call xf86AddInputDriver and a font renderer\n"
 | 
						|
	"module did not call LoadFont. This message can also be printed if\n"
 | 
						|
	"the module is in the incorrect directory.";
 | 
						|
	checkerLegend[CHECKER_NO_OPTIONS_AVAILABLE] =
 | 
						|
	"The driver does not have an AvailableOptions function, or that\n"
 | 
						|
	"function is returning NULL. If the driver is returning NULL, and\n"
 | 
						|
	"really does not need any options from XF86Config, than the message\n"
 | 
						|
	"can be ignored.";
 | 
						|
	checkerLegend[CHECKER_NO_VENDOR_CHIPSET] =
 | 
						|
	"The checker could not fetch the PCI chipset/vendor information from\n"
 | 
						|
	"the module. The checker currently wraps xf86PrintChipsets and\n"
 | 
						|
	"xf86MatchPciInstances to read the information from the module.";
 | 
						|
	checkerLegend[CHECKER_CANNOT_VERIFY_CHIPSET] =
 | 
						|
	"The vendor id was not found, so it is not possible to search the list\n"
 | 
						|
	"of chipsets.";
 | 
						|
	checkerLegend[CHECKER_OPTION_UNUSED] =
 | 
						|
	"The option description is defined in the Options file, but the option\n"
 | 
						|
	"was name not retrieved when calling the module AvailableOptions.";
 | 
						|
	checkerLegend[CHECKER_NOMATCH_CHIPSET_STRINGS] =
 | 
						|
	"The string specified in the module does not match the one in\n"
 | 
						|
	"common/xf86PciInfo.h";
 | 
						|
	checkerLegend[CHECKER_CHIPSET_NOT_LISTED] =
 | 
						|
	"This means that common/xf86PciInfo.h does not have an entry for the\n"
 | 
						|
	"given vendor and id.";
 | 
						|
	checkerLegend[CHECKER_CHIPSET_NOT_SUPPORTED] =
 | 
						|
	"The chipset is listed in common/xf86PciInfo.h, but the driver does\n"
 | 
						|
	"not support it, or does not list it in the chipsets fetched by the checker.";
 | 
						|
	checkerLegend[CHECKER_CHIPSET_NO_VENDOR] =
 | 
						|
	"The vendor id specified to xf86MatchPciInstances is not defined in\n"
 | 
						|
	"common/xf86PciInfo.h";
 | 
						|
	checkerLegend[CHECKER_NO_CHIPSETS] =
 | 
						|
	"No chipsets were passed to xf86MatchPciIntances.";
 | 
						|
	checkerLegend[CHECKER_FILE_MODULE_NAME_MISMATCH] =
 | 
						|
	"The module name string does not match the the modname field of the\n"
 | 
						|
	"XF86ModuleVersionInfo structure. This generally is not an error, but\n"
 | 
						|
	"to may be a good idea to use the same string to avoid confusion.";
 | 
						|
    }
 | 
						|
 | 
						|
    if (XF86Module_path == NULL) {
 | 
						|
	XF86Module_path = malloc(strlen(XFree86Dir) + strlen(modules) + 2);
 | 
						|
	sprintf(XF86Module_path, "%s/%s", XFree86Dir, modules);
 | 
						|
    }
 | 
						|
 | 
						|
    if (loaderPath == NULL || strcmp(XF86Module_path, loaderPath))
 | 
						|
	loaderPath = strdup(XF86Module_path);
 | 
						|
    else
 | 
						|
	/* nothing new */
 | 
						|
	return (True);
 | 
						|
 | 
						|
    if (!noverify) {
 | 
						|
	options_ok = InitializeOptionsDatabase();
 | 
						|
	InitializePciInfo();
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = 0; module_types[i] != NullModule; i++) {
 | 
						|
	xf86cfgLoaderInitList(module_types[i]);
 | 
						|
	if (!noverify)
 | 
						|
	    ErrorF("================= Checking modules of type \"%s\" =================\n",
 | 
						|
		   module_strs[module_types[i]]);
 | 
						|
 | 
						|
	if (loaderList) {
 | 
						|
	    for (ploaderList = loaderList; *ploaderList; ploaderList++) {
 | 
						|
		signal_caught = 0;
 | 
						|
		signal(SIGTRAP, sig_handler);
 | 
						|
		signal(SIGBUS, sig_handler);
 | 
						|
		signal(SIGSEGV, sig_handler);
 | 
						|
		signal(SIGILL, sig_handler);
 | 
						|
		signal(SIGFPE, sig_handler);
 | 
						|
		if (sigsetjmp(jmp, 1) == 0) {
 | 
						|
		    if (!noverify) {
 | 
						|
			int ok, nfont_modules;
 | 
						|
 | 
						|
			nfont_modules = numFontModules;
 | 
						|
			error_level = 0;
 | 
						|
			ErrorF("CHECK MODULE %s\n", *ploaderList);
 | 
						|
			if ((ok = xf86cfgCheckModule()) == 0) {
 | 
						|
			    CheckMsg(CHECKER_LOAD_FAILED,
 | 
						|
				     "ERROR Failed to load module.\n");
 | 
						|
			    error_level += 50;
 | 
						|
			}
 | 
						|
			else if (module_type != module_types[i]) {
 | 
						|
			    CheckMsg(CHECKER_RECOGNIZED_AS,
 | 
						|
				     "WARNING %s recognized as a \"%s\"\n", *ploaderList,
 | 
						|
				     module_strs[module_type]);
 | 
						|
			    ++error_level;
 | 
						|
			}
 | 
						|
			if (ok) {
 | 
						|
			    if (options_ok) {
 | 
						|
				if ((module_options == NULL || module_options->option == NULL) &&
 | 
						|
				    module_type != GenericModule) {
 | 
						|
				    CheckMsg(CHECKER_NO_OPTIONS_AVAILABLE,
 | 
						|
					     "WARNING Not a generic module, but no options available.\n");
 | 
						|
				    ++error_level;
 | 
						|
				}
 | 
						|
				else if (module_options && strcmp(module_options->name, *ploaderList) == 0) {
 | 
						|
				    ErrorF("  CHECK OPTIONS\n");
 | 
						|
				    option = module_options->option;
 | 
						|
 | 
						|
				    while (option->name) {
 | 
						|
					XmuSnprintf(query, sizeof(query), "%s.%s", *ploaderList, option->name);
 | 
						|
					for (ptr = query, ptr2 = query2; *ptr; ptr++) {
 | 
						|
					    if (*ptr != '_' && *ptr != ' ' && *ptr != '\t')
 | 
						|
						*ptr2 = tolower(*ptr);
 | 
						|
					}
 | 
						|
					*ptr2 = '\0';
 | 
						|
					/* all resources are in lowercase */
 | 
						|
					if (!XrmGetResource(options_xrm, query2, "Module.Option", &type, &value) ||
 | 
						|
					    value.addr == NULL) {
 | 
						|
					    CheckMsg(CHECKER_OPTION_DESCRIPTION_MISSING,
 | 
						|
						     "WARNING no description for %s\n", query);
 | 
						|
					    ++error_level;
 | 
						|
					}
 | 
						|
					++option;
 | 
						|
				    }
 | 
						|
 | 
						|
				    /* now do a linear search for Options file entries that are not
 | 
						|
				     * in the driver.
 | 
						|
				     */
 | 
						|
				    names[0] = XrmPermStringToQuark(module_options->name);
 | 
						|
				    classes[0] = XrmPermStringToQuark("Option");
 | 
						|
				    names[1] = classes[1] = NULLQUARK;
 | 
						|
				    (void)XrmEnumerateDatabase(options_xrm, (XrmNameList)&names, (XrmClassList)&classes,
 | 
						|
							       XrmEnumOneLevel, EnumDatabase, NULL);
 | 
						|
				}
 | 
						|
			    }
 | 
						|
			    else {
 | 
						|
				CheckMsg(CHECKER_OPTIONS_FILE_MISSING,
 | 
						|
					 "ERROR Options file missing.\n");
 | 
						|
				error_level += 10;
 | 
						|
			    }
 | 
						|
 | 
						|
			    if (module_type == VideoModule &&
 | 
						|
				(module_options == NULL || module_options->vendor < 0 ||
 | 
						|
				 module_options->chipsets == NULL)) {
 | 
						|
				CheckMsg(CHECKER_NO_VENDOR_CHIPSET,
 | 
						|
				         "WARNING No vendor/chipset information available.\n");
 | 
						|
				++error_level;
 | 
						|
			    }
 | 
						|
			    else if (module_type == VideoModule) {
 | 
						|
				if (module_options == NULL) {
 | 
						|
				    /* No description for this, if this happen,
 | 
						|
				     * something really strange happened. */
 | 
						|
				    ErrorF("  ERROR No module_options!?!\n");
 | 
						|
				    error_level += 50;
 | 
						|
				}
 | 
						|
				else {
 | 
						|
				    ErrorF("  CHECK CHIPSETS\n");
 | 
						|
				    CheckChipsets(module_options, &error_level);
 | 
						|
				}
 | 
						|
			    }
 | 
						|
 | 
						|
			    /* font modules check */
 | 
						|
			    if (module_type == FontRendererModule) {
 | 
						|
				if (strcmp(*ploaderList, font_module->name)) {
 | 
						|
				    /* not an error */
 | 
						|
				    ErrorF("  NOTICE FontModule->name specification mismatch: \"%s\" \"%s\"\n",
 | 
						|
					   *ploaderList, font_module->name);
 | 
						|
				}
 | 
						|
				if (nfont_modules + 1 != numFontModules) {
 | 
						|
				    /* not an error */
 | 
						|
				    ErrorF("  NOTICE font module \"%s\" loaded more than one font renderer.\n",
 | 
						|
					   *ploaderList);
 | 
						|
				}
 | 
						|
			    }
 | 
						|
			    else if (nfont_modules != numFontModules) {
 | 
						|
				ErrorF("  WARNING number of font modules changed from %d to %d.\n",
 | 
						|
				       nfont_modules, numFontModules);
 | 
						|
				++error_level;
 | 
						|
			    }
 | 
						|
			}
 | 
						|
			ErrorF("  SUMMARY error_level set to %d.\n\n", error_level);
 | 
						|
		    }
 | 
						|
		    else
 | 
						|
			(void)xf86cfgCheckModule();
 | 
						|
		}
 | 
						|
		signal(SIGTRAP, SIG_DFL);
 | 
						|
		signal(SIGBUS, SIG_DFL);
 | 
						|
		signal(SIGSEGV, SIG_DFL);
 | 
						|
		signal(SIGILL, SIG_DFL);
 | 
						|
		signal(SIGFPE, SIG_DFL);
 | 
						|
	    }
 | 
						|
	    xf86cfgLoaderFreeList();
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    ErrorF("  ERROR Failed to initialize module list.\n");
 | 
						|
    }
 | 
						|
 | 
						|
    if (!noverify) {
 | 
						|
	ErrorF("===================================== LEGEND ===============================\n");
 | 
						|
	ErrorF("NOTICE lines are just informative.\n");
 | 
						|
	ErrorF("WARNING lines add 1 to error_level.\n");
 | 
						|
	ErrorF("ERROR lines add 2 or more (based on the severity of the error) to error_level.\n\n");
 | 
						|
	for (i = 0; i <= CHECKER_LAST_MESSAGE; i++)
 | 
						|
	    if (checkerErrors[i]) {
 | 
						|
		ErrorF("%3d\n%s\n\n", i, checkerLegend[i]);
 | 
						|
	    }
 | 
						|
    }
 | 
						|
 | 
						|
    return (True);
 | 
						|
}
 | 
						|
#endif
 |