| 1 | // ========== Copyright Header Begin ========================================== |
| 2 | // |
| 3 | // OpenSPARC T2 Processor File: disk_parser.cc |
| 4 | // Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. |
| 5 | // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. |
| 6 | // |
| 7 | // The above named program is free software; you can redistribute it and/or |
| 8 | // modify it under the terms of the GNU General Public |
| 9 | // License version 2 as published by the Free Software Foundation. |
| 10 | // |
| 11 | // The above named program is distributed in the hope that it will be |
| 12 | // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | // General Public License for more details. |
| 15 | // |
| 16 | // You should have received a copy of the GNU General Public |
| 17 | // License along with this work; if not, write to the Free Software |
| 18 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. |
| 19 | // |
| 20 | // ========== Copyright Header End ============================================ |
| 21 | #include "disk.h" |
| 22 | #include "arg.h" |
| 23 | |
| 24 | #define MAX_SCSI_DISK_PARTITIONS 8 |
| 25 | #define MAX_SCSI_TARGETS 16 |
| 26 | #define LINE_BUF_SIZE 1024 |
| 27 | |
| 28 | extern SCSIDisk *parser_disk; |
| 29 | |
| 30 | |
| 31 | static char ** parse_args (const char * string, int * pargc) { |
| 32 | int allocc = 4; |
| 33 | int argc = 0; |
| 34 | char ** pargv = (char**) calloc (allocc, sizeof(char*)); |
| 35 | char * tmpstr = (char*) strdup (string); |
| 36 | char * s = tmpstr; |
| 37 | char * ps; |
| 38 | int inquotes = 0; /* when we're inside " quotes */ |
| 39 | int backslash = 0; /* yet another flag... */ |
| 40 | |
| 41 | if (pargv == NULL) |
| 42 | return NULL; |
| 43 | |
| 44 | // remove leading white space |
| 45 | // |
| 46 | while (isspace(*s)) { |
| 47 | if ((*s == '\0') || (*s == '\n')) { |
| 48 | *pargc = 0; |
| 49 | return NULL; |
| 50 | } |
| 51 | ++s; |
| 52 | } |
| 53 | |
| 54 | ps = s; |
| 55 | for (;;) { |
| 56 | |
| 57 | inquotes = 0; |
| 58 | while (!isspace(*s) || inquotes) { |
| 59 | if (*s == '"') |
| 60 | inquotes = ! inquotes; |
| 61 | ++s; |
| 62 | if (*s == '\0') |
| 63 | goto EOLINE; |
| 64 | } |
| 65 | |
| 66 | // copy parsed arg into argv |
| 67 | *s = '\0'; |
| 68 | pargv[argc++] = (char*) strdup (ps); |
| 69 | ++s; |
| 70 | |
| 71 | // re-allocate argv if we have too many args |
| 72 | // |
| 73 | if (argc >= allocc) { |
| 74 | allocc *= 2; |
| 75 | pargv = (char**) realloc (pargv, sizeof(char*) * allocc); |
| 76 | } |
| 77 | |
| 78 | // |
| 79 | // skip white space between words |
| 80 | // |
| 81 | while (isspace(*s)) { |
| 82 | ++s; |
| 83 | } |
| 84 | if ((*s == '\0') || (*s == '\n')) |
| 85 | goto DONE; |
| 86 | ps = s; |
| 87 | } |
| 88 | |
| 89 | EOLINE: |
| 90 | pargv[argc++] = (char*) strdup (ps); |
| 91 | DONE: |
| 92 | free(tmpstr); |
| 93 | |
| 94 | *pargc = argc; |
| 95 | return pargv; |
| 96 | } |
| 97 | |
| 98 | |
| 99 | static void free_args (int argc, char ** argv) { |
| 100 | int i; |
| 101 | for (i = 0; i < argc; i++) { |
| 102 | free(argv[i]); |
| 103 | } |
| 104 | if (argc > 0) |
| 105 | free(argv); |
| 106 | } |
| 107 | |
| 108 | |
| 109 | char *process_str(const char *src) { |
| 110 | int ls = strlen(src); |
| 111 | char *dst = (char *)calloc(ls+1, sizeof(char)); |
| 112 | |
| 113 | if ((src[0] == '\'' /* single quoted */ |
| 114 | && src[ls-1] == '\'') |
| 115 | || (src[0] == '"' /* or double quoted cases */ |
| 116 | && src[ls-1] == '"')) { |
| 117 | |
| 118 | bcopy(src+1, dst, ls-2); |
| 119 | |
| 120 | } else if (ls > 9 /* dotted hex case */ |
| 121 | && src[2] == '.' && src[5] == '.' && src[8] == '.') { |
| 122 | |
| 123 | int j=0; |
| 124 | for (int i=0; i<ls; i++) |
| 125 | if (src[i] != '.') dst[j++] = src[i]; |
| 126 | |
| 127 | } else { /* default case */ |
| 128 | |
| 129 | bcopy(src, dst, ls); |
| 130 | } |
| 131 | |
| 132 | return(dst); |
| 133 | } |
| 134 | |
| 135 | |
| 136 | // Scan through the whole file to parse all configs related to a target |
| 137 | // 0: succeed, -1: fail |
| 138 | int scsi_parse_config(const char * fname, FILE *fp, int target) { |
| 139 | char line_buf[LINE_BUF_SIZE]; |
| 140 | char *charP; |
| 141 | int result; |
| 142 | int lineno; |
| 143 | int argc; |
| 144 | char **argv; |
| 145 | int i; |
| 146 | |
| 147 | // for basic config |
| 148 | int target_id, disk_id, partition_id; |
| 149 | bool write_flag, vtoc_part; |
| 150 | |
| 151 | // for extended config |
| 152 | const char *vendor_id, *product_id, *revision_id; |
| 153 | const char *serial_no; |
| 154 | const char *prodserial_no, *brdserial_no; |
| 155 | const char *port_wwn, *node_wwn; |
| 156 | const char *rdelay; |
| 157 | const char *bytes_per_sector; |
| 158 | const char *sectors_per_track; |
| 159 | const char *tracks_per_cylinder; |
| 160 | const char *debug_file; |
| 161 | const char *debug_level; |
| 162 | const char *disk_delay; |
| 163 | |
| 164 | fseek(fp, 0, SEEK_SET); |
| 165 | lineno = 0; |
| 166 | argc = 0; |
| 167 | |
| 168 | while (charP = fgets(line_buf, LINE_BUF_SIZE, fp)) { |
| 169 | // initializing variables |
| 170 | target_id = disk_id = partition_id = -1; |
| 171 | write_flag = false; |
| 172 | vtoc_part = false; |
| 173 | |
| 174 | vendor_id = product_id = revision_id = NULL; |
| 175 | serial_no = NULL; |
| 176 | prodserial_no = brdserial_no = NULL; |
| 177 | port_wwn = node_wwn = NULL; |
| 178 | rdelay = NULL; |
| 179 | bytes_per_sector = NULL; |
| 180 | sectors_per_track = NULL; |
| 181 | tracks_per_cylinder = NULL; |
| 182 | debug_file = NULL; |
| 183 | debug_level = NULL; |
| 184 | disk_delay = NULL; |
| 185 | |
| 186 | // lineno is used to track the error |
| 187 | lineno++; |
| 188 | |
| 189 | // parse all parameters into arg |
| 190 | free_args(argc, argv); |
| 191 | argv = parse_args(charP, &argc); |
| 192 | |
| 193 | // empty line |
| 194 | if (argc == 0) |
| 195 | continue; |
| 196 | |
| 197 | // comment line |
| 198 | if (*argv[0] == '#') |
| 199 | continue; |
| 200 | |
| 201 | if (argc < 2) { |
| 202 | free_args(argc, argv); |
| 203 | fprintf(stderr, "%s: lineno %d: insufficient args.\n", fname, lineno); |
| 204 | return(-1); |
| 205 | } |
| 206 | |
| 207 | result = sscanf(argv[0], "t%dd%ds%x", &target_id, &disk_id, &partition_id); |
| 208 | if (result != 3) { |
| 209 | free_args(argc, argv); |
| 210 | fprintf(stderr, "%s: lineno %d: wrong disk partition name.\n", fname, lineno); |
| 211 | return(-1); |
| 212 | } |
| 213 | |
| 214 | if (target_id >= MAX_SCSI_TARGETS || target_id < 0) { |
| 215 | free_args(argc, argv); |
| 216 | fprintf(stderr, "%s: lineno %d: invalid target id.\n", fname, lineno); |
| 217 | return(-1); |
| 218 | } |
| 219 | |
| 220 | if (disk_id != 0) { |
| 221 | free_args(argc, argv); |
| 222 | fprintf(stderr, "%s: lineno %d: invalid disk id.\n", fname, lineno); |
| 223 | return(-1); |
| 224 | } |
| 225 | |
| 226 | if (partition_id >= MAX_SCSI_DISK_PARTITIONS || partition_id < 0) { |
| 227 | free_args(argc, argv); |
| 228 | fprintf(stderr, "%s: lineno %d: invalid partition id.\n", fname, lineno); |
| 229 | return(-1); |
| 230 | } |
| 231 | |
| 232 | if (target_id != target) |
| 233 | continue; |
| 234 | |
| 235 | i = 2; |
| 236 | |
| 237 | if (i < argc) { |
| 238 | bool other_params = false; |
| 239 | |
| 240 | // the third parameter is either "ro", or "rw", or "vtoc", or others |
| 241 | if (strcmp(argv[i], "ro") == 0) { |
| 242 | write_flag = false; |
| 243 | i++; |
| 244 | } else if (strcmp(argv[i], "rw") == 0) { |
| 245 | write_flag = true; |
| 246 | i++; |
| 247 | } else if (strcmp(argv[i], "vtoc") == 0) { |
| 248 | vtoc_part = true; |
| 249 | i++; |
| 250 | } else { |
| 251 | other_params = true; |
| 252 | } |
| 253 | |
| 254 | // the fourth parameter is "votc", or others |
| 255 | if (!other_params && i < argc) { |
| 256 | if (strcmp(argv[i], "vtoc") == 0) { |
| 257 | vtoc_part = true; |
| 258 | i++; |
| 259 | } |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | for (; i < argc; i++) { |
| 264 | if (argval ("vendor-id", argv[i], &vendor_id)) |
| 265 | parser_disk->set_vendor_id(process_str(vendor_id)); |
| 266 | else if (argval ("product-id", argv[i], &product_id)) |
| 267 | parser_disk->set_product_id(process_str(product_id)); |
| 268 | else if (argval ("revision-id", argv[i], &revision_id)) |
| 269 | parser_disk->set_revision_id(process_str(revision_id)); |
| 270 | else if (argval ("serial-no", argv[i], &serial_no)) |
| 271 | parser_disk->set_serial_no(process_str(serial_no)); |
| 272 | else if (argval ("prodserial-no", argv[i], &prodserial_no)) |
| 273 | parser_disk->set_prodserial_no(process_str(prodserial_no)); |
| 274 | else if (argval ("brdserial-no", argv[i], &brdserial_no)) |
| 275 | parser_disk->set_brdserial_no(process_str(brdserial_no)); |
| 276 | else if (argval ("port-wwn", argv[i], &port_wwn)) |
| 277 | parser_disk->set_port_wwn(process_str(port_wwn)); |
| 278 | else if (argval ("node-wwn", argv[i], &node_wwn)) |
| 279 | parser_disk->set_node_wwn(process_str(node_wwn)); |
| 280 | else if (argval ("bytes/sector", argv[i], &bytes_per_sector)) |
| 281 | parser_disk->set_bytes_per_sector(atoi(bytes_per_sector)); |
| 282 | else if (argval ("sectors/track", argv[i], §ors_per_track)) |
| 283 | parser_disk->set_sectors_per_track(atoi(sectors_per_track)); |
| 284 | else if (argval ("tracks/cylinder", argv[i], &tracks_per_cylinder)) |
| 285 | parser_disk->set_tracks_per_cylinder(atoi(tracks_per_cylinder)); |
| 286 | else if (argval ("dd", argv[i], &disk_delay)) |
| 287 | parser_disk->set_disk_delay(process_str(disk_delay)); |
| 288 | else if (argval ("debug-file", argv[i], &debug_file)) |
| 289 | parser_disk->set_debug_file(process_str(debug_file)); |
| 290 | else if (argval ("debug-level", argv[i], &debug_level)) |
| 291 | parser_disk->set_debug_level(atoi(debug_level)); |
| 292 | else { |
| 293 | free_args(argc, argv); |
| 294 | fprintf(stderr, "%s: lineno %d: unrecognized arg.\n", fname, lineno); |
| 295 | return(-1); |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | // add one partition |
| 300 | parser_disk->add_partition(partition_id, argv[1], write_flag, vtoc_part); |
| 301 | } |
| 302 | |
| 303 | return 0; |
| 304 | } |