|
31 | 31 |
|
32 | 32 | #define ATOM_DEBUG
|
33 | 33 |
|
| 34 | +#include "atomfirmware.h" |
34 | 35 | #include "atom.h"
|
35 | 36 | #include "atom-names.h"
|
36 | 37 | #include "atom-bits.h"
|
@@ -1299,12 +1300,168 @@ static void atom_index_iio(struct atom_context *ctx, int base)
|
1299 | 1300 | }
|
1300 | 1301 | }
|
1301 | 1302 |
|
| 1303 | +static void atom_get_vbios_name(struct atom_context *ctx) |
| 1304 | +{ |
| 1305 | + unsigned char *p_rom; |
| 1306 | + unsigned char str_num; |
| 1307 | + unsigned short off_to_vbios_str; |
| 1308 | + unsigned char *c_ptr; |
| 1309 | + int name_size; |
| 1310 | + int i; |
| 1311 | + |
| 1312 | + const char *na = "--N/A--"; |
| 1313 | + char *back; |
| 1314 | + |
| 1315 | + p_rom = ctx->bios; |
| 1316 | + |
| 1317 | + str_num = *(p_rom + OFFSET_TO_GET_ATOMBIOS_NUMBER_OF_STRINGS); |
| 1318 | + if (str_num != 0) { |
| 1319 | + off_to_vbios_str = |
| 1320 | + *(unsigned short *)(p_rom + OFFSET_TO_GET_ATOMBIOS_STRING_START); |
| 1321 | + |
| 1322 | + c_ptr = (unsigned char *)(p_rom + off_to_vbios_str); |
| 1323 | + } else { |
| 1324 | + /* do not know where to find name */ |
| 1325 | + memcpy(ctx->name, na, 7); |
| 1326 | + ctx->name[7] = 0; |
| 1327 | + return; |
| 1328 | + } |
| 1329 | + |
| 1330 | + /* |
| 1331 | + * skip the atombios strings, usually 4 |
| 1332 | + * 1st is P/N, 2nd is ASIC, 3rd is PCI type, 4th is Memory type |
| 1333 | + */ |
| 1334 | + for (i = 0; i < str_num; i++) { |
| 1335 | + while (*c_ptr != 0) |
| 1336 | + c_ptr++; |
| 1337 | + c_ptr++; |
| 1338 | + } |
| 1339 | + |
| 1340 | + /* skip the following 2 chars: 0x0D 0x0A */ |
| 1341 | + c_ptr += 2; |
| 1342 | + |
| 1343 | + name_size = strnlen(c_ptr, STRLEN_LONG - 1); |
| 1344 | + memcpy(ctx->name, c_ptr, name_size); |
| 1345 | + back = ctx->name + name_size; |
| 1346 | + while ((*--back) == ' ') |
| 1347 | + ; |
| 1348 | + *(back + 1) = '\0'; |
| 1349 | +} |
| 1350 | + |
| 1351 | +static void atom_get_vbios_date(struct atom_context *ctx) |
| 1352 | +{ |
| 1353 | + unsigned char *p_rom; |
| 1354 | + unsigned char *date_in_rom; |
| 1355 | + |
| 1356 | + p_rom = ctx->bios; |
| 1357 | + |
| 1358 | + date_in_rom = p_rom + OFFSET_TO_VBIOS_DATE; |
| 1359 | + |
| 1360 | + ctx->date[0] = '2'; |
| 1361 | + ctx->date[1] = '0'; |
| 1362 | + ctx->date[2] = date_in_rom[6]; |
| 1363 | + ctx->date[3] = date_in_rom[7]; |
| 1364 | + ctx->date[4] = '/'; |
| 1365 | + ctx->date[5] = date_in_rom[0]; |
| 1366 | + ctx->date[6] = date_in_rom[1]; |
| 1367 | + ctx->date[7] = '/'; |
| 1368 | + ctx->date[8] = date_in_rom[3]; |
| 1369 | + ctx->date[9] = date_in_rom[4]; |
| 1370 | + ctx->date[10] = ' '; |
| 1371 | + ctx->date[11] = date_in_rom[9]; |
| 1372 | + ctx->date[12] = date_in_rom[10]; |
| 1373 | + ctx->date[13] = date_in_rom[11]; |
| 1374 | + ctx->date[14] = date_in_rom[12]; |
| 1375 | + ctx->date[15] = date_in_rom[13]; |
| 1376 | + ctx->date[16] = '\0'; |
| 1377 | +} |
| 1378 | + |
| 1379 | +static unsigned char *atom_find_str_in_rom(struct atom_context *ctx, char *str, int start, |
| 1380 | + int end, int maxlen) |
| 1381 | +{ |
| 1382 | + unsigned long str_off; |
| 1383 | + unsigned char *p_rom; |
| 1384 | + unsigned short str_len; |
| 1385 | + |
| 1386 | + str_off = 0; |
| 1387 | + str_len = strnlen(str, maxlen); |
| 1388 | + p_rom = ctx->bios; |
| 1389 | + |
| 1390 | + for (; start <= end; ++start) { |
| 1391 | + for (str_off = 0; str_off < str_len; ++str_off) { |
| 1392 | + if (str[str_off] != *(p_rom + start + str_off)) |
| 1393 | + break; |
| 1394 | + } |
| 1395 | + |
| 1396 | + if (str_off == str_len || str[str_off] == 0) |
| 1397 | + return p_rom + start; |
| 1398 | + } |
| 1399 | + return NULL; |
| 1400 | +} |
| 1401 | + |
| 1402 | +static void atom_get_vbios_pn(struct atom_context *ctx) |
| 1403 | +{ |
| 1404 | + unsigned char *p_rom; |
| 1405 | + unsigned short off_to_vbios_str; |
| 1406 | + unsigned char *vbios_str; |
| 1407 | + int count; |
| 1408 | + |
| 1409 | + off_to_vbios_str = 0; |
| 1410 | + p_rom = ctx->bios; |
| 1411 | + |
| 1412 | + if (*(p_rom + OFFSET_TO_GET_ATOMBIOS_NUMBER_OF_STRINGS) != 0) { |
| 1413 | + off_to_vbios_str = |
| 1414 | + *(unsigned short *)(p_rom + OFFSET_TO_GET_ATOMBIOS_STRING_START); |
| 1415 | + |
| 1416 | + vbios_str = (unsigned char *)(p_rom + off_to_vbios_str); |
| 1417 | + } else { |
| 1418 | + vbios_str = p_rom + OFFSET_TO_VBIOS_PART_NUMBER; |
| 1419 | + } |
| 1420 | + |
| 1421 | + if (*vbios_str == 0) { |
| 1422 | + vbios_str = atom_find_str_in_rom(ctx, BIOS_ATOM_PREFIX, 3, 1024, 64); |
| 1423 | + if (vbios_str == NULL) |
| 1424 | + vbios_str += sizeof(BIOS_ATOM_PREFIX) - 1; |
| 1425 | + } |
| 1426 | + if (vbios_str != NULL && *vbios_str == 0) |
| 1427 | + vbios_str++; |
| 1428 | + |
| 1429 | + if (vbios_str != NULL) { |
| 1430 | + count = 0; |
| 1431 | + while ((count < BIOS_STRING_LENGTH) && vbios_str[count] >= ' ' && |
| 1432 | + vbios_str[count] <= 'z') { |
| 1433 | + ctx->vbios_pn[count] = vbios_str[count]; |
| 1434 | + count++; |
| 1435 | + } |
| 1436 | + |
| 1437 | + ctx->vbios_pn[count] = 0; |
| 1438 | + } |
| 1439 | +} |
| 1440 | + |
| 1441 | +static void atom_get_vbios_version(struct atom_context *ctx) |
| 1442 | +{ |
| 1443 | + unsigned char *vbios_ver; |
| 1444 | + |
| 1445 | + /* find anchor ATOMBIOSBK-AMD */ |
| 1446 | + vbios_ver = atom_find_str_in_rom(ctx, BIOS_VERSION_PREFIX, 3, 1024, 64); |
| 1447 | + if (vbios_ver != NULL) { |
| 1448 | + /* skip ATOMBIOSBK-AMD VER */ |
| 1449 | + vbios_ver += 18; |
| 1450 | + memcpy(ctx->vbios_ver_str, vbios_ver, STRLEN_NORMAL); |
| 1451 | + } else { |
| 1452 | + ctx->vbios_ver_str[0] = '\0'; |
| 1453 | + } |
| 1454 | +} |
| 1455 | + |
1302 | 1456 | struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios)
|
1303 | 1457 | {
|
1304 | 1458 | int base;
|
1305 | 1459 | struct atom_context *ctx =
|
1306 | 1460 | kzalloc(sizeof(struct atom_context), GFP_KERNEL);
|
1307 | 1461 | char *str;
|
| 1462 | + struct _ATOM_ROM_HEADER *atom_rom_header; |
| 1463 | + struct _ATOM_MASTER_DATA_TABLE *master_table; |
| 1464 | + struct _ATOM_FIRMWARE_INFO *atom_fw_info; |
1308 | 1465 | u16 idx;
|
1309 | 1466 |
|
1310 | 1467 | if (!ctx)
|
@@ -1353,6 +1510,21 @@ struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios)
|
1353 | 1510 | strlcpy(ctx->vbios_version, str, sizeof(ctx->vbios_version));
|
1354 | 1511 | }
|
1355 | 1512 |
|
| 1513 | + atom_rom_header = (struct _ATOM_ROM_HEADER *)CSTR(base); |
| 1514 | + if (atom_rom_header->usMasterDataTableOffset != 0) { |
| 1515 | + master_table = (struct _ATOM_MASTER_DATA_TABLE *) |
| 1516 | + CSTR(atom_rom_header->usMasterDataTableOffset); |
| 1517 | + if (master_table->ListOfDataTables.FirmwareInfo != 0) { |
| 1518 | + atom_fw_info = (struct _ATOM_FIRMWARE_INFO *) |
| 1519 | + CSTR(master_table->ListOfDataTables.FirmwareInfo); |
| 1520 | + ctx->version = atom_fw_info->ulFirmwareRevision; |
| 1521 | + } |
| 1522 | + } |
| 1523 | + |
| 1524 | + atom_get_vbios_name(ctx); |
| 1525 | + atom_get_vbios_pn(ctx); |
| 1526 | + atom_get_vbios_date(ctx); |
| 1527 | + atom_get_vbios_version(ctx); |
1356 | 1528 |
|
1357 | 1529 | return ctx;
|
1358 | 1530 | }
|
|
0 commit comments