static void __devinit tg3_read_bc_ver(struct tg3 *tp)
 {
        u32 val, offset, start, ver_offset;
-       int i;
+       int i, dst_off;
        bool newver = false;
 
        if (tg3_nvram_read(tp, 0xc, &offset) ||
                        newver = true;
        }
 
+       dst_off = strlen(tp->fw_ver);
+
        if (newver) {
-               if (tg3_nvram_read(tp, offset + 8, &ver_offset))
+               if (TG3_VER_SIZE - dst_off < 16 ||
+                   tg3_nvram_read(tp, offset + 8, &ver_offset))
                        return;
 
                offset = offset + ver_offset - start;
                        if (tg3_nvram_read_be32(tp, offset + i, &v))
                                return;
 
-                       memcpy(tp->fw_ver + i, &v, sizeof(v));
+                       memcpy(tp->fw_ver + dst_off + i, &v, sizeof(v));
                }
        } else {
                u32 major, minor;
                major = (ver_offset & TG3_NVM_BCVER_MAJMSK) >>
                        TG3_NVM_BCVER_MAJSFT;
                minor = ver_offset & TG3_NVM_BCVER_MINMSK;
-               snprintf(&tp->fw_ver[0], 32, "v%d.%02d", major, minor);
+               snprintf(&tp->fw_ver[dst_off], TG3_VER_SIZE - dst_off,
+                        "v%d.%02d", major, minor);
        }
 }
 
 {
        u32 offset, major, minor, build;
 
-       tp->fw_ver[0] = 's';
-       tp->fw_ver[1] = 'b';
-       tp->fw_ver[2] = '\0';
+       strncat(tp->fw_ver, "sb", TG3_VER_SIZE - strlen(tp->fw_ver) - 1);
 
        if ((val & TG3_EEPROM_SB_FORMAT_MASK) != TG3_EEPROM_SB_FORMAT_1)
                return;
        if (minor > 99 || build > 26)
                return;
 
-       snprintf(&tp->fw_ver[2], 30, " v%d.%02d", major, minor);
+       offset = strlen(tp->fw_ver);
+       snprintf(&tp->fw_ver[offset], TG3_VER_SIZE - offset,
+                " v%d.%02d", major, minor);
 
        if (build > 0) {
-               tp->fw_ver[8] = 'a' + build - 1;
-               tp->fw_ver[9] = '\0';
+               offset = strlen(tp->fw_ver);
+               if (offset < TG3_VER_SIZE - 1)
+                       tp->fw_ver[offset] = 'a' + build - 1;
        }
 }
 
 static void __devinit tg3_read_fw_ver(struct tg3 *tp)
 {
        u32 val;
+       bool vpd_vers = false;
 
-       if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) {
-               tp->fw_ver[0] = 's';
-               tp->fw_ver[1] = 'b';
-               tp->fw_ver[2] = '\0';
+       if (tp->fw_ver[0] != 0)
+               vpd_vers = true;
 
+       if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) {
+               strcat(tp->fw_ver, "sb");
                return;
        }
 
                return;
 
        if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
-            (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
-               return;
+            (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) || vpd_vers)
+               goto done;
 
        tg3_read_mgmtfw_ver(tp);
 
+done:
        tp->fw_ver[TG3_VER_SIZE - 1] = 0;
 }