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 25const 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 86const 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} 114EXPORT_SYMBOL(__TBITransStr); 115