2018-10-15 15:47:01 +11:00
// SPDX-License-Identifier: MIT
2009-08-21 13:21:01 +10:00
/* utility to create the register check tables
* this includes inlined list . h safe for userspace .
*
* Copyright 2009 Jerome Glisse
* Copyright 2009 Red Hat Inc .
*
* Authors :
* Jerome Glisse
* Dave Airlie
*/
# include <sys/types.h>
# include <stdlib.h>
# include <string.h>
# include <stdio.h>
# include <regex.h>
# include <libgen.h>
# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
/**
* container_of - cast a member of a structure out to the containing structure
* @ ptr : the pointer to the member .
* @ type : the type of the container struct this is embedded in .
* @ member : the name of the member within the struct .
*
*/
# define container_of(ptr, type, member) ({ \
2009-08-27 11:51:23 +10:00
const typeof ( ( ( type * ) 0 ) - > member ) * __mptr = ( ptr ) ; \
( type * ) ( ( char * ) __mptr - offsetof ( type , member ) ) ; } )
2009-08-21 13:21:01 +10:00
/*
* Simple doubly linked list implementation .
*
* Some of the internal functions ( " __xxx " ) are useful when
* manipulating whole lists rather than single entries , as
* sometimes we already know the next / prev entries and we can
* generate better code by using them directly rather than
* using the generic single - entry routines .
*/
struct list_head {
struct list_head * next , * prev ;
} ;
static inline void INIT_LIST_HEAD ( struct list_head * list )
{
list - > next = list ;
list - > prev = list ;
}
/*
* Insert a new entry between two known consecutive entries .
*
* This is only for internal list manipulation where we know
* the prev / next entries already !
*/
# ifndef CONFIG_DEBUG_LIST
static inline void __list_add ( struct list_head * new ,
2009-08-27 11:51:23 +10:00
struct list_head * prev , struct list_head * next )
2009-08-21 13:21:01 +10:00
{
next - > prev = new ;
new - > next = next ;
new - > prev = prev ;
prev - > next = new ;
}
# else
extern void __list_add ( struct list_head * new ,
2009-08-27 11:51:23 +10:00
struct list_head * prev , struct list_head * next ) ;
2009-08-21 13:21:01 +10:00
# endif
/**
* list_add_tail - add a new entry
* @ new : new entry to be added
* @ head : list head to add it before
*
* Insert a new entry before the specified head .
* This is useful for implementing queues .
*/
static inline void list_add_tail ( struct list_head * new , struct list_head * head )
{
__list_add ( new , head - > prev , head ) ;
}
/**
* list_entry - get the struct for this entry
* @ ptr : the & struct list_head pointer .
* @ type : the type of the struct this is embedded in .
2014-11-14 05:09:55 +04:00
* @ member : the name of the list_head within the struct .
2009-08-21 13:21:01 +10:00
*/
# define list_entry(ptr, type, member) \
container_of ( ptr , type , member )
/**
* list_for_each_entry - iterate over list of given type
* @ pos : the type * to use as a loop cursor .
* @ head : the head for your list .
2014-11-14 05:09:55 +04:00
* @ member : the name of the list_head within the struct .
2009-08-21 13:21:01 +10:00
*/
# define list_for_each_entry(pos, head, member) \
for ( pos = list_entry ( ( head ) - > next , typeof ( * pos ) , member ) ; \
& pos - > member ! = ( head ) ; \
pos = list_entry ( pos - > member . next , typeof ( * pos ) , member ) )
struct offset {
2009-08-27 11:51:23 +10:00
struct list_head list ;
unsigned offset ;
2009-08-21 13:21:01 +10:00
} ;
struct table {
2009-08-27 11:51:23 +10:00
struct list_head offsets ;
unsigned offset_max ;
unsigned nentry ;
unsigned * table ;
char * gpu_prefix ;
2009-08-21 13:21:01 +10:00
} ;
2009-10-16 15:12:13 -07:00
static struct offset * offset_new ( unsigned o )
2009-08-21 13:21:01 +10:00
{
2009-08-27 11:51:23 +10:00
struct offset * offset ;
offset = ( struct offset * ) malloc ( sizeof ( struct offset ) ) ;
if ( offset ) {
INIT_LIST_HEAD ( & offset - > list ) ;
offset - > offset = o ;
}
return offset ;
2009-08-21 13:21:01 +10:00
}
2009-10-16 15:12:13 -07:00
static void table_offset_add ( struct table * t , struct offset * offset )
2009-08-21 13:21:01 +10:00
{
2009-08-27 11:51:23 +10:00
list_add_tail ( & offset - > list , & t - > offsets ) ;
2009-08-21 13:21:01 +10:00
}
2009-10-16 15:12:13 -07:00
static void table_init ( struct table * t )
2009-08-21 13:21:01 +10:00
{
2009-08-27 11:51:23 +10:00
INIT_LIST_HEAD ( & t - > offsets ) ;
t - > offset_max = 0 ;
t - > nentry = 0 ;
t - > table = NULL ;
2009-08-21 13:21:01 +10:00
}
2009-10-16 15:12:13 -07:00
static void table_print ( struct table * t )
2009-08-21 13:21:01 +10:00
{
2009-08-27 11:51:23 +10:00
unsigned nlloop , i , j , n , c , id ;
nlloop = ( t - > nentry + 3 ) / 4 ;
c = t - > nentry ;
printf ( " static const unsigned %s_reg_safe_bm[%d] = { \n " , t - > gpu_prefix ,
t - > nentry ) ;
for ( i = 0 , id = 0 ; i < nlloop ; i + + ) {
n = 4 ;
if ( n > c )
n = c ;
c - = n ;
for ( j = 0 ; j < n ; j + + ) {
if ( j = = 0 )
printf ( " \t " ) ;
else
printf ( " " ) ;
printf ( " 0x%08X, " , t - > table [ id + + ] ) ;
}
printf ( " \n " ) ;
}
printf ( " }; \n " ) ;
2009-08-21 13:21:01 +10:00
}
2009-10-16 15:12:13 -07:00
static int table_build ( struct table * t )
2009-08-21 13:21:01 +10:00
{
2009-08-27 11:51:23 +10:00
struct offset * offset ;
unsigned i , m ;
t - > nentry = ( ( t - > offset_max > > 2 ) + 31 ) / 32 ;
t - > table = ( unsigned * ) malloc ( sizeof ( unsigned ) * t - > nentry ) ;
if ( t - > table = = NULL )
return - 1 ;
memset ( t - > table , 0xff , sizeof ( unsigned ) * t - > nentry ) ;
list_for_each_entry ( offset , & t - > offsets , list ) {
i = ( offset - > offset > > 2 ) / 32 ;
m = ( offset - > offset > > 2 ) & 31 ;
m = 1 < < m ;
t - > table [ i ] ^ = m ;
}
return 0 ;
2009-08-21 13:21:01 +10:00
}
static char gpu_name [ 10 ] ;
2009-10-16 15:12:13 -07:00
static int parser_auth ( struct table * t , const char * filename )
2009-08-21 13:21:01 +10:00
{
2009-08-27 11:51:23 +10:00
FILE * file ;
regex_t mask_rex ;
regmatch_t match [ 4 ] ;
char buf [ 1024 ] ;
size_t end ;
int len ;
int done = 0 ;
int r ;
unsigned o ;
struct offset * offset ;
char last_reg_s [ 10 ] ;
int last_reg ;
if ( regcomp
( & mask_rex , " (0x[0-9a-fA-F]*) *([_a-zA-Z0-9]*) " , REG_EXTENDED ) ) {
fprintf ( stderr , " Failed to compile regular expression \n " ) ;
return - 1 ;
}
file = fopen ( filename , " r " ) ;
if ( file = = NULL ) {
fprintf ( stderr , " Failed to open: %s \n " , filename ) ;
return - 1 ;
}
fseek ( file , 0 , SEEK_END ) ;
end = ftell ( file ) ;
fseek ( file , 0 , SEEK_SET ) ;
/* get header */
2010-01-07 02:59:31 +03:00
if ( fgets ( buf , 1024 , file ) = = NULL ) {
fclose ( file ) ;
2009-08-27 11:51:23 +10:00
return - 1 ;
2010-01-07 02:59:31 +03:00
}
2009-08-27 11:51:23 +10:00
/* first line will contain the last register
* and gpu name */
2013-12-17 15:05:39 +00:00
sscanf ( buf , " %9s %9s " , gpu_name , last_reg_s ) ;
2009-08-27 11:51:23 +10:00
t - > gpu_prefix = gpu_name ;
last_reg = strtol ( last_reg_s , NULL , 16 ) ;
do {
2011-02-05 20:51:53 +01:00
if ( fgets ( buf , 1024 , file ) = = NULL ) {
fclose ( file ) ;
2009-08-27 11:51:23 +10:00
return - 1 ;
2011-02-05 20:51:53 +01:00
}
2009-08-27 11:51:23 +10:00
len = strlen ( buf ) ;
if ( ftell ( file ) = = end )
done = 1 ;
if ( len ) {
r = regexec ( & mask_rex , buf , 4 , match , 0 ) ;
if ( r = = REG_NOMATCH ) {
} else if ( r ) {
fprintf ( stderr ,
" Error matching regular expression %d in %s \n " ,
r , filename ) ;
2011-02-05 20:51:53 +01:00
fclose ( file ) ;
2009-08-27 11:51:23 +10:00
return - 1 ;
} else {
buf [ match [ 0 ] . rm_eo ] = 0 ;
buf [ match [ 1 ] . rm_eo ] = 0 ;
buf [ match [ 2 ] . rm_eo ] = 0 ;
o = strtol ( & buf [ match [ 1 ] . rm_so ] , NULL , 16 ) ;
offset = offset_new ( o ) ;
table_offset_add ( t , offset ) ;
if ( o > t - > offset_max )
t - > offset_max = o ;
}
}
} while ( ! done ) ;
fclose ( file ) ;
if ( t - > offset_max < last_reg )
t - > offset_max = last_reg ;
return table_build ( t ) ;
2009-08-21 13:21:01 +10:00
}
int main ( int argc , char * argv [ ] )
{
2009-08-27 11:51:23 +10:00
struct table t ;
if ( argc ! = 2 ) {
fprintf ( stderr , " Usage: %s <authfile> \n " , argv [ 0 ] ) ;
exit ( 1 ) ;
}
table_init ( & t ) ;
if ( parser_auth ( & t , argv [ 1 ] ) ) {
fprintf ( stderr , " Failed to parse file %s \n " , argv [ 1 ] ) ;
return - 1 ;
}
table_print ( & t ) ;
return 0 ;
2009-08-21 13:21:01 +10:00
}