• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * tbistring.c
3  *
4  * Copyright (C) 2001, 2002, 2003, 2005, 2007, 2012 Imagination Technologies.
5  *
6  * This program is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation.
9  *
10  * String table functions provided as part of the thread binary interface for
11  * Meta processors
12  */
13 
14 #include <linux/export.h>
15 #include <linux/string.h>
16 #include <asm/tbx.h>
17 
18 /*
19  * There are not any functions to modify the string table currently, if these
20  * are required at some later point I suggest having a seperate module and
21  * ensuring that creating new entries does not interfere with reading old
22  * entries in any way.
23  */
24 
__TBIFindStr(const TBISTR * start,const char * str,int match_len)25 const TBISTR *__TBIFindStr(const TBISTR *start,
26 			   const char *str, int match_len)
27 {
28 	const TBISTR *search = start;
29 	bool exact = true;
30 	const TBISEG *seg;
31 
32 	if (match_len < 0) {
33 		/* Make match_len always positive for the inner loop */
34 		match_len = -match_len;
35 		exact = false;
36 	} else {
37 		/*
38 		 * Also support historic behaviour, which expected match_len to
39 		 * include null terminator
40 		 */
41 		if (match_len && str[match_len-1] == '\0')
42 			match_len--;
43 	}
44 
45 	if (!search) {
46 		/* Find global string table segment */
47 		seg = __TBIFindSeg(NULL, TBID_SEG(TBID_THREAD_GLOBAL,
48 						  TBID_SEGSCOPE_GLOBAL,
49 						  TBID_SEGTYPE_STRING));
50 
51 		if (!seg || seg->Bytes < sizeof(TBISTR))
52 			/* No string table! */
53 			return NULL;
54 
55 		/* Start of string table */
56 		search = seg->pGAddr;
57 	}
58 
59 	for (;;) {
60 		while (!search->Tag)
61 			/* Allow simple gaps which are just zero initialised */
62 			search = (const TBISTR *)((const char *)search + 8);
63 
64 		if (search->Tag == METAG_TBI_STRE) {
65 			/* Reached the end of the table */
66 			search = NULL;
67 			break;
68 		}
69 
70 		if ((search->Len >= match_len) &&
71 		    (!exact || (search->Len == match_len + 1)) &&
72 		    (search->Tag != METAG_TBI_STRG)) {
73 			/* Worth searching */
74 			if (!strncmp(str, (const char *)search->String,
75 				     match_len))
76 				break;
77 		}
78 
79 		/* Next entry */
80 		search = (const TBISTR *)((const char *)search + search->Bytes);
81 	}
82 
83 	return search;
84 }
85 
__TBITransStr(const char * str,int len)86 const void *__TBITransStr(const char *str, int len)
87 {
88 	const TBISTR *search = NULL;
89 	const void *res = NULL;
90 
91 	for (;;) {
92 		/* Search onwards */
93 		search = __TBIFindStr(search, str, len);
94 
95 		/* No translation returns NULL */
96 		if (!search)
97 			break;
98 
99 		/* Skip matching entries with no translation data */
100 		if (search->TransLen != METAG_TBI_STRX) {
101 			/* Calculate base of translation string */
102 			res = (const char *)search->String +
103 				((search->Len + 7) & ~7);
104 			break;
105 		}
106 
107 		/* Next entry */
108 		search = (const TBISTR *)((const char *)search + search->Bytes);
109 	}
110 
111 	/* Return base address of translation data or NULL */
112 	return res;
113 }
114 EXPORT_SYMBOL(__TBITransStr);
115