From a1ab70deb30a74a46f568658393a41ee22feb34b Mon Sep 17 00:00:00 2001 From: ultramagnus_tcv Date: Fri, 22 Apr 2016 11:10:39 -0500 Subject: [PATCH] Major Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After Rob Justice fixed a problem with driver counting, everyone decided that sub_driver names needed to be put in the CSV, but how. First, we worked out how to get the sub_driver names properly. Once done, we introduced a new field in the CSV to hold the sub_driver names. Lastly, we placed the sub_driver names in the field, each delimited by a pipe “|” character. A new EXAMPLE.SOS.DRIVER file has been introduced, one that Rob Justice provided which contains a .MOUSE sub_driver under .CONSOLE and a new EXAMPLE.OUTPUT.csv has been offered as well. --- Driv3rs.py | 32 ++++++++++++++++++++++++-------- EXAMPLE.OUTPUT.csv | 15 +++++++++------ EXAMPLE.SOS.DRIVER | Bin 15872 -> 28672 bytes 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/Driv3rs.py b/Driv3rs.py index fed9a65..825268f 100644 --- a/Driv3rs.py +++ b/Driv3rs.py @@ -2,7 +2,7 @@ from struct import unpack; import argparse import hashlib import os.path - + parser = argparse.ArgumentParser( prog='Driv3rs.py', formatter_class=argparse.RawDescriptionHelpFormatter, @@ -12,6 +12,7 @@ parser = argparse.ArgumentParser( * imaged Apple /// disks. By Mike Whalen, Michael Sternberg * * and Paul Hagstrom. Please submit pull requests to Github. * * https://github.com/thecompu/Driv3rs * +* Special Thanks to Rob Justice for Bug Fixes and Suggestions * **************************************************************** ''') group = parser.add_mutually_exclusive_group() @@ -210,7 +211,7 @@ for i in range(0,len(drivers_list)): # and the CFFA3000 and populated a dictionary. This dictionary # will get more k/v pairs as time goes on. mfg = readUnpack(2, type = 'b') - drivers_list[i]['mfg']=mfg + drivers_list[i]['mfg']=mfg # version bytes are integer values stored across two bytes. # a nibble corresponds to a major version number, one of two minor @@ -263,16 +264,28 @@ for i in range(0,len(drivers_list)): # generally we enter each major drive DIB and look at the link field. # if the link field is not 0000, we know there are other DIBs. # we can open up a new loop to run through the interior DIBs until -# we encount a 0000 in a link field, then we stop. +# we encounter a 0000 in a link field, then we stop. for i in range(0,len(drivers_list)): total_devs = 0 SOSfile.seek(drivers_list[i]['dib_start'],0) + sub_sub = "" + drivers_list[i]['subdrivers'] = sub_sub #initialize subdrivers dict k/v sub_loop = True while sub_loop: total_devs = total_devs + 1 - sub_link = readUnpack(2, type = 'b') #link to next DIB + sub_link = readUnpack(2, type = 'b') #link to next DIB if sub_link != 0x0000: SOSfile.seek(drivers_list[i]['dib_start'] + sub_link,0) #link is from DIB start + SOSfile.seek(4,1) #skip over dib Entry pointer + subname_len = readUnpack(1, type = '1') + subname = readUnpack(subname_len, type = 't') + sub_temp = drivers_list[i]['subdrivers'] + if sub_temp != "" and sub_link != 0x0000: + sub_temp = sub_temp + ' ' + '|' + ' ' + subname + drivers_list[i]['subdrivers'] = sub_temp + else: + drivers_list[i]['subdrivers'] = subname + SOSfile.seek(drivers_list[i]['dib_start'] + sub_link,0) else: sub_loop = False drivers_list[i]['num_devices'] = total_devs @@ -287,7 +300,7 @@ exists = os.path.exists(output_csv) if exists == False: csvout = open(output_csv, 'w') csvout.write('SOS_DRIVER_FILE,comment_start,comment_len,comment_txt,' + \ - 'dib_start,link_ptr,entry,name_len,name,flag,slot_num,num_devices,unit,' +\ + 'dib_start,link_ptr,entry,name_len,majorname,flag,slot_num,num_devices,subnames,unit,' +\ 'dev_type,block_num,mfg,version,dcb_length,driver_md5,code_md5\n') else: csvout = open(output_csv, 'a') @@ -295,7 +308,7 @@ else: for i in range(0,len(drivers_list)): csvout.write(disk_img + ',') #comment start hex or decimal - if args.rawhex: + if args.rawhex: csvout.write(hex(drivers_list[i]['comment_start']) + ',') else: csvout.write(str(drivers_list[i]['comment_start']) + ',') @@ -307,7 +320,7 @@ for i in range(0,len(drivers_list)): csvout.write(str(drivers_list[i]['comment_len']) + ',') #comment - csvout.write('"' + drivers_list[i]['comment_txt'] + '"' + ',') + csvout.write('"' + drivers_list[i]['comment_txt'] + '"' + ',') #dib_start hex or decimal if args.rawhex: @@ -340,7 +353,7 @@ for i in range(0,len(drivers_list)): if args.rawhex: csvout.write(hex(drivers_list[i]['flag']) + ',') elif args.rawdec: - csvout.write(str(drivers_list[i]['flag']) + ',') + csvout.write(str(drivers_list[i]['flag']) + ',') else: if drivers_list[i]['flag'] == 192: csvout.write('"' + 'ACTIVE, Load on Boundary' + '"' ',') @@ -361,6 +374,9 @@ for i in range(0,len(drivers_list)): else: csvout.write(str(drivers_list[i]['num_devices']) + ',') +#sub_driver names ascii only + csvout.write(drivers_list[i]['subdrivers'] + ',' ) + #unit hex or decimal if args.rawhex: csvout.write(hex(drivers_list[i]['unit']) + ',') diff --git a/EXAMPLE.OUTPUT.csv b/EXAMPLE.OUTPUT.csv index f1e50b8..86ceacc 100644 --- a/EXAMPLE.OUTPUT.csv +++ b/EXAMPLE.OUTPUT.csv @@ -1,6 +1,9 @@ -SOS_DRIVER_FILE,comment_start,comment_len,comment_txt,dib_start,link_ptr,entry,name_len,name,flag,slot_num,num_devices,unit,dev_type,block_num,mfg,version,dcb_length,driver_md5,code_md5 -EXAMPLE.SOS.DRIVER,1324,0,"None",1328,1086,959,6,.FMTD1,"ACTIVE, Load on Boundary",0,4,0,"Character Device, Write-Only, Formatter",280,Apple Computer,1.10,0,b2a1c11d43f86c8857d243008a40f93f,4d61c0816eaf51db819de7007c83c2df -EXAMPLE.SOS.DRIVER,2708,0,"None",2712,0,267,10,.SILENTYPE,INACTIVE,0,1,0,"Character Device, Write-Only, Silentype",0,Apple Computer,1.04,17,ca6db71e02668bbdad801ec1c3a17fce,3c7a572346944991f88ed502669e249d -EXAMPLE.SOS.DRIVER,7538,0,"None",7542,0,192,8,.PRINTER,ACTIVE,0,1,0,"Character Device, Write-Only, RS232 Printer",0,Apple Computer,1.10,5,cdccaf496ea198eb3aef21b36156c028,719171eb8eb663fb1d21a0809bc44ceb -EXAMPLE.SOS.DRIVER,8444,0,"None",8448,0,266,8,.CONSOLE,ACTIVE,0,1,0,"Character Device, Read-Write, System Console",0,Apple Computer,1.12,0,501be146123c9ae217bca5dba60b9610,9e539ef09c806b44768d4641f3f18922 -EXAMPLE.SOS.DRIVER,13550,78,"Apple /// CFFA3000 (Compact Flash For Apple 3000) Driver by David Schmidt 2011",13632,34,306,11,.CFFA3000D1,ACTIVE,1,8,0,"Block Device, CFFA3000",0,David Schmidt,1.00,0,0f3d973b201027cc64a32dba15d6dc16,c5d1b3a23a2dca59644a58d7441d65f8 +SOS_DRIVER_FILE,comment_start,comment_len,comment_txt,dib_start,link_ptr,entry,name_len,majorname,flag,slot_num,num_devices,subnames,unit,dev_type,block_num,mfg,version,dcb_length,driver_md5,code_md5 +SELECTOR.SOS.DRIVER,1324,57,"Graphics Driver -- Copyright Apple Computer, Inc. 1980-83",1385,0,542,7,.GRAFIX,ACTIVE,0,1,,0,"Character Device, Read-Write, Graphics Screen",0,Apple Computer,1.30,150,b994e229d4bed57e1fa8f74ee0c2b4e8,08940bacf47311e4a57dbc18601f3fbd +SELECTOR.SOS.DRIVER,6836,52,"Audio Driver -- Copyright Apple Computer, Inc. 1980",6892,0,90,6,.AUDIO,ACTIVE,0,1,,0,"Character Device, Write-Only, Sound Port",0,Apple Computer,1.00,0,851f6d79a088d6707615112a721176ad,6a49cbf2e41b0a1ea7caceb378abc968 +SELECTOR.SOS.DRIVER,7554,67,"Disk /// Formatter Driver -- Copyright Apple Computer, Inc. 1980-83",7625,1024,882,6,.FMTD1,"ACTIVE, Load on Boundary",0,4,.FMTD2 | .FMTD3 | .FMTD4,0,"Character Device, Write-Only, Formatter",280,Apple Computer,1.30,0,43d94d124fb815c2bb8c3ad56a7a82f5,ba59588e74343ea5a03667709f944313 +SELECTOR.SOS.DRIVER,8920,76,"Built-in Serial Port RS-232 Driver -- Copyright Apple Computer, Inc. 1981-83",9000,0,626,6,.RS232,ACTIVE,0,1,,0,"Character Device, Read-Write, Onboard RS232",0,Apple Computer,1.30,12,ddc18277ca38785e89e2ccb35b3d4a9e,a3c461333bf93af12cfbb87242d060c0 +SELECTOR.SOS.DRIVER,11291,68,"Parallel Printer Driver -- Copyright (C) 1983 by Apple Computer Inc.",11363,0,311,11,.PARPRINTER,ACTIVE,1,1,,0,"Character Device, Write-Only, Parallel Printer",0,Apple Computer,1.30,5,fdf9f348f02e99b31c150c85997ff3f3,9ef431eedad20c3b9199b375b8ca1289 +SELECTOR.SOS.DRIVER,12435,57,"Silentype driver - Copyright Apple Computer, Inc. 1980-83",12496,0,267,10,.SILENTYPE,ACTIVE,0,1,,0,"Character Device, Write-Only, Silentype",0,Apple Computer,1.04,17,49e5b29e7624c6ba24c4d58205a8e811,7fd8f61392c5f7b9a94328e719051aca +SELECTOR.SOS.DRIVER,17322,78,"Apple /// CFFA3000 (Compact Flash For Apple 3000) Driver by David Schmidt 2011",17404,34,306,8,.PROFILE,ACTIVE,1,8,.CFFA3000D2 | .CFFA3000D3 | .CFFA3000D4 | .CFFA3000D5 | .CFFA3000D6 | .CFFA3000D7 | .CFFA3000D8,0,"Block Device, CFFA3000",0,David Schmidt,1.00,0,f1ea73cf74321e96f30dfb8cbbbaa608,c5d1b3a23a2dca59644a58d7441d65f8 +SELECTOR.SOS.DRIVER,19256,56,"Console Driver -- Copyright Apple Computer, Inc. 1980-83",19316,4003,4125,8,.CONSOLE,ACTIVE,4,2,.MOUSE,0,"Character Device, Read-Write, System Console",0,Apple Computer,1.31,0,932a431aa85d5b203900e0550c2e7fa0,04ef7b41bef10aa53969da421f89e9b3 diff --git a/EXAMPLE.SOS.DRIVER b/EXAMPLE.SOS.DRIVER index 18579a620b2bfc41df610eabcebada3b21714fb0..b7cc4721dc0f63df1fe11401187a008d97d84f58 100644 GIT binary patch delta 18965 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 L*4B)r!w>u)7Wqyo delta 6547 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