All times are UTC - 5 hours [ DST ]


Forum rules


Please do not post questions about data recovery cases here (use this forum instead). This forum is for topics on finding new ways to recover data. Accessing firmware, writing programs, reading bits off the platter, recovering data from dust...



Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: Analysis of Seagate LOD firmware image file
PostPosted: March 24th, 2014, 17:19 
Offline
User avatar

Joined: September 8th, 2009, 18:21
Posts: 15461
Location: Australia
Analysis of Seagate LOD firmware image file

Seagate's F3 drives (since 7200.11) incorporate modular code in serial flash memory (aka "ROM"). The ROM contains program code plus "adaptive" data modules which are unique to each drive. Whereas previous models updated the ROM as a complete unit, current models update only the code sections. The update may also address certain firmware modules in the System Area (SA) on the platters.

The following tutorial examines the SD1A2D.LOD file in the MooseDT-SD1A-2D-8-16-32MB.iso package that was discussed in the following post:

Analysis of Seagate F3 Firmware Update:
viewtopic.php?t=28250&p=194229#p194229

The LOD image is comprised of several blocks of code separated by headers. Each header has a size of 64 bytes (= 0x40). Forum member Moltke has written a ZOC script that parses the LOD file and extracts each of these headers (see attachment).

Here is/was the ZOC script:
http://malthus.zapto.org/viewtopic.php? ... 3162#p3162
http://malthus.zapto.org/viewtopic.php? ... 3273#p3273
http://malthus.zapto.org/download/file.php?id=602

Code:
/* REXX */
   cls
   DIR_PART="C:\_DUMPS"
MAIN:
   TASK=ZocRequestList("SELECT: ","ST_SUMM","LOD_STRUCT")
   if TASK= -1 then exit
   if TASK= 1 then signal ST_LOD
      
ST_SUMM:
   call GET_FILE ,MAIN 
   NUM=GETSUMM(abst)                             
   say IN_FILE||" SUMM: "||c2x(NUM)||"h"
   SIGNAL MAIN   
ST_LOD:
   call GET_FILE "SELECT SEAGATE LOD FILE:",MAIN                               
   CURRENT_OFFSET=1 ; LEN_BLOCK=x2d(40)
   if c2d(substr(abst,x2d(0E)+1,1))<>7 then do
UNKNFRMT:  say "UNKNOWN LOD FORMAT"
      signal ST_LOD
   end
   else do
      BLOCK=substr(abst,CURRENT_OFFSET,LEN_BLOCK)
      NUM=GETSUMM(BLOCK)
      if NUM<>substr(BLOCK,x2d(3E)+1,2) then signal UNKNFRMT
   end
   LOG_FILE=F_CREATE(DIR_PART,"LOD_HEADERS.TXT") ; t1=time(S)      

   do while CURRENT_OFFSET<length(abst)
      BLOCK=substr(abst,CURRENT_OFFSET,LEN_BLOCK)
      call TO_FILE "LOD_"||d2x(CURRENT_OFFSET-1,OFFS_FORMAT)||".BIN",BLOCK
      call DO_HEX BLOCK,CURRENT_OFFSET-1,LOG_FILE
      NEXT_ADDR=c2d(reverse(substr(BLOCK,x2d(10)+1,4)))
      CURRENT_OFFSET=CURRENT_OFFSET+LEN_BLOCK+NEXT_ADDR
   end
   call stream LOG_FILE,"C","CLOSE"
   say "SAVED TO:"
   say LOG_FILE||" in "||abs(time(S)-t1)||" sec"
   SIGNAL MAIN
      
BYE:   exit

/* ============================================================== */
F_CREATE:
   PARSE ARG _DIR,_FILE     
   IF STREAM(_DIR,"C","QUERY EXISTS")="" THEN DO
           CALL ZOCSHELL MD _DIR,1
   END
   _TMP=_DIR||"\"||_FILE
   IF STREAM(_TMP,"C","QUERY EXISTS")<>"" THEN DO
           CALL ZOCSHELL DEL _TMP,1
   END
   CALL STREAM _TMP,"C","OPEN WRITE"
RETURN _TMP
/* ============================================================== */
GET_FILE:
   parse arg _MSG,_TO
   if _TO="" then _TO=MAIN
   if _MSG="" then _MSG="SELECT FILE:"
L0:   IN_FILE= ZocGetFilename(_MSG, DIR_PART||"\*.*") 
   if IN_FILE="##CANCEL##" then signal value _TO
   
   if stream(IN_FILE,"C","QUERY EXISTS")="" then do
          say "["||IN_FILE||"] NOT FOUND.RETRY"
      signal L0
   end
   
   abst=charin(IN_FILE,1,chars(IN_FILE))
   call stream IN_FILE,"C","CLOSE"
   if length(abst)=0 then do
      say "LENGTH FILE=0.TRY NEXT FILE."
      signal L0
   end
   
   OFFS_FORMAT=length(d2x(length(abst)))
   if OFFS_FORMAT < 4 then OFFS_FORMAT=4       
   
   i=lastpos("\",IN_FILE)
   DIR_PART=left(IN_FILE,i-1)
   F_PART=substr(IN_FILE,i+1,) 
RETURN
/* ============================================================== */
TO_FILE:
   parse arg _FNAME,_BUFF                         
   if _BUFF="" then _BUFF=abst
   OUT_FILE=F_CREATE(DIR_PART,_FNAME) 
   call charout OUT_FILE,_BUFF   
   call stream OUT_FILE,"C","CLOSE"
   say ""
   say "SAVED TO:"
   say OUT_FILE
RETURN   
/* ============================================================== */
FLUSH:
   PARSE ARG _FILE,V2
   if _FILE="" then _FILE=OUT_FILE
   SAY V2
   CALL CHAROUT _FILE,V2||X2C(0D0A)
RETURN
/* ============================================================== */
GETSUMM:
   parse arg BUFF
   LEN_BUFF=length(BUFF) ; SUMM=0   
   do i=1 to LEN_BUFF by 2
      _word=reverse(substr(BUFF,i,2))
      SUMM=SUMM+c2d(_word)
      if SUMM>=65536 then SUMM=SUMM-65536
   end
   if SUMM=0 then SUMM=c2d(_word)                   
   else SUMM=65536-SUMM
RETURN   reverse(d2c(SUMM))
/* ============================================================== */
DO_HEX:     
   PARSE ARG _BUFF,_OFFS,F_DUMP 
   LB=length(_BUFF)                                 
   DIGITS_FOR_OFFSET=length(d2x(_OFFS+LB))
   if DIGITS_FOR_OFFSET < 4 then DIGITS_FOR_OFFSET=4
   
   _STR="ADDR:|"
   IF DIGITS_FOR_OFFSET>4 THEN _STR=COPIES(" ",DIGITS_FOR_OFFSET-4)||_STR
      
   DO K=0 TO 15
      _STR=_STR||D2X(K,02)||"|"
   END
   BORD1=copies("-",length(_STR))
   
   CALL FLUSH F_DUMP,BORD1   
   CALL FLUSH F_DUMP,_STR                       
   CALL FLUSH F_DUMP,BORD1     
   
   do k=1 to LB
   
      if (k-1)//16=0 then do
         BINTOHEX=d2x((k-1)+_OFFS,DIGITS_FOR_OFFSET)||":"
         BINTOASC=""
      end   

      CHAR=substr(_BUFF,k,1)
      BINTOHEX=BINTOHEX||" "||c2x(CHAR)
      if c2d(CHAR)<32 | c2d(CHAR)>127 then CHAR=x2c(2E)
      BINTOASC=BINTOASC||CHAR
      if k//16=0 then CALL FLUSH F_DUMP,BINTOHEX||copies(" ",3)||BINTOASC
      
   end
   
   REST=16-length(BINTOASC)
     if REST<>0 then do
      BINTOHEX=BINTOHEX||copies(" ",REST*2)
      CALL FLUSH F_DUMP,BINTOHEX||copies(" ",3)||BINTOASC
   end
   
   CALL FLUSH F_DUMP,""
RETURN


Here is a header example (LOD_18988.BIN):

Code:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000  17 06 03 13 01 00 00 00 80 27 00 00 00 00 42 04  ........?'....B.
00000010  38 16 06 00 0D 60 02 00 22 01 50 15 01 22 09 20  8....`..".P..".
00000020  08 00 00 00 78 16 06 00 00 00 00 00 00 00 00 00  ....x...........
00000030  00 00 00 00 00 00 00 00 00 00 00 00 00 00 D4 D5  ..............OO


The header is located at offset 0x18988 within the LOD file. It has a size of 0x40 bytes.

Offset 0x10 within the header specifies the size of the block of code that follows, namely 0x61638. Therefore this block of code occupies the range 189C8-79FFF (0x189C8 = 0x18988 + 0x40).

Proceeding in this manner, we are able to extract the following 10 code blocks:

Code:
     Range         Size (hex / decimal)
---------------------------------------
1    00200-021FF    2000    8,192
2    02400-153FF   13000   77,824
3    15500-165FF    1100    4,352
4    16800-187FF    2000    8,192
5    189C8-79FFF   61638  398,904
6    7A040-85DFF    BDC0   48,576
7    86000-B5FFF   30000  196,608
8    B6200-D61FF   20000  131,072
9    D6400-E63FF   10000   65,536
10   E6600-F65FF   10000   65,536


In order to identify each of these modules, I compared them against an actual resource dump for an ST3500320AS model with SD1A firmware:

http://files.hddguru.com/download/Non-P ... 20SD1A.rar

Code block #5 (189C8-79FFF) is the first part of the ROM (CP15.CP in the SD1A resource dump).

Here is the header section of the ROM:

Code:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000  A7 25 00 00 40 00 00 00 40 82 00 00 0D 2C 04 00
00000010  02 38 00 00 04 38 16 06 06 48 18 06 03 58 9C 06
00000020  0B 58 CC 07 05 58 DD 07 0E 70 FD 07 00 00 00 08


Offsets 0x10 - 0x2F define the various code and data modules within the ROM.

Code:
----------------------------
ID  start   size (hex / dec)
----------------------------
02  000038  61600  398848
04  061638  00210     528
06  061848  08410   33808
03  069C58  13000   77824
0B  07CC58  01100    4352
05  07DD58  02018    8216
0E  07FD70  00290     656
00  080000


After comparing the code blocks against the SD1A resource dump, it is evident that the update modifies 3 sections of the ROM, plus at least 3 firmware modules in the SA, namely MODs 1D, 1E, and 34. There are 2 code blocks which I couldn't match against any resource, so I have no idea where they go. One of them contains ConGen text strings, but strangely the resource dump contains no such text.

    02400-153FF = ROM module 03
    15500-165FF = ROM module 0B
    189C8-79FFF = first part of ROM
    7A040-85DFF = SA module 34
    86000-B5FFF ---- contains Congen text strings
    B6200-D61FF ---- header similar to MODs 1D / 1E , probably MOD 1F
    D6400-E63FF = SA module 1E
    E6600-F65FF = SA module 1D

The following blocks of code are identical:

Code:
00200-021FF.bin  8,192   
16800-187FF.bin  8,192


They do not appear to be firmware modules. Instead they appear to be some kind of firmware loader, perhaps for ROM flashing. In fact I have extracted identical code blocks from Seagate's Savvio10K5-Compass-SAS-StdOEM-0004 and Dell's CS09 SAS firmware updates.

I suspect that the code block at 86000-B5FFF might be SA module 1F, but I can't understand why it doesn't show up in the resource dump. Perhaps the dump is from an earlier SD1A package version?

The above modules have the following functions:

    1D --- Physical Overlay File 0
    1E --- Physical Overlay File 1
    1F --- Physical Overlay File 2
    34 --- Packed CONGEN XML definition

Module 34 appears to contain ConGen stuff in compressed form.


References:

ZOC (Terminal Emulator, Telnet Client, SSH/SSH2 Client):
http://www.emtec.com/download.html#zocfiles

Original article:
http://malthus.zapto.org/viewtopic.php? ... 3166#p3166


Attachments:
LOD_HEADERS.zip [981 Bytes]
Downloaded 1443 times

_________________
A backup a day keeps DR away.
Top
 Profile  
 
 Post subject: Re: Analysis of Seagate LOD firmware image file
PostPosted: January 15th, 2022, 18:39 
Offline
User avatar

Joined: January 6th, 2019, 11:58
Posts: 14
Location: Türkiye
:shock: can i convert this scripts to image patcher sw.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


Who is online

Users browsing this forum: Google [Bot] and 22 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group