@@ -5,39 +5,139 @@ use crate::mapper::DeviceMapper;
55use crate :: settings:: LoadSettings ;
66use binaryninja:: binary_view:: { BinaryView , BinaryViewBase , BinaryViewExt } ;
77use binaryninja:: command:: Command ;
8+ use binaryninja:: interaction:: { Form , FormInputField } ;
89use binaryninja:: logger:: Logger ;
910use binaryninja:: workflow:: { activity, Activity , AnalysisContext , Workflow } ;
1011use log:: LevelFilter ;
12+ use std:: path:: PathBuf ;
13+ use svd_parser:: ValidateLevel ;
14+
15+ pub struct LoadFileField ;
16+
17+ impl LoadFileField {
18+ pub fn field ( ) -> FormInputField {
19+ FormInputField :: OpenFileName {
20+ prompt : "File Path" . to_string ( ) ,
21+ // TODO: This is called extension but is really a filter.
22+ extension : Some ( "*.svd" . to_string ( ) ) ,
23+ default : None ,
24+ value : None ,
25+ }
26+ }
27+
28+ pub fn from_form ( form : & Form ) -> Option < PathBuf > {
29+ let field = form. get_field_with_name ( "File Path" ) ?;
30+ let field_value = field. try_value_string ( ) ?;
31+ Some ( PathBuf :: from ( field_value) )
32+ }
33+ }
34+
35+ pub struct AddCommentsField ;
36+
37+ impl AddCommentsField {
38+ pub fn field ( default : bool ) -> FormInputField {
39+ FormInputField :: Checkbox {
40+ prompt : "Add Comments" . to_string ( ) ,
41+ default : Some ( default) ,
42+ value : false ,
43+ }
44+ }
45+
46+ pub fn from_form ( form : & Form ) -> Option < bool > {
47+ let field = form. get_field_with_name ( "Add Comments" ) ?;
48+ let field_value = field. try_value_int ( ) ?;
49+ match field_value {
50+ 1 => Some ( true ) ,
51+ _ => Some ( false ) ,
52+ }
53+ }
54+ }
55+
56+ pub struct AddBitfieldsField ;
57+
58+ impl AddBitfieldsField {
59+ pub fn field ( default : bool ) -> FormInputField {
60+ FormInputField :: Checkbox {
61+ prompt : "Add Bitfields" . to_string ( ) ,
62+ default : Some ( default) ,
63+ value : false ,
64+ }
65+ }
66+
67+ pub fn from_form ( form : & Form ) -> Option < bool > {
68+ let field = form. get_field_with_name ( "Add Bitfields" ) ?;
69+ let field_value = field. try_value_int ( ) ?;
70+ match field_value {
71+ 1 => Some ( true ) ,
72+ _ => Some ( false ) ,
73+ }
74+ }
75+ }
76+
77+ pub struct AddMemoryRegionsField ;
78+
79+ impl AddMemoryRegionsField {
80+ pub fn field ( default : bool ) -> FormInputField {
81+ FormInputField :: Checkbox {
82+ prompt : "Add Memory Regions" . to_string ( ) ,
83+ default : Some ( default) ,
84+ value : false ,
85+ }
86+ }
87+
88+ pub fn from_form ( form : & Form ) -> Option < bool > {
89+ let field = form. get_field_with_name ( "Add Memory Regions" ) ?;
90+ let field_value = field. try_value_int ( ) ?;
91+ match field_value {
92+ 1 => Some ( true ) ,
93+ _ => Some ( false ) ,
94+ }
95+ }
96+ }
1197
1298struct LoadSVDFile ;
1399
14100impl Command for LoadSVDFile {
15101 fn action ( & self , view : & BinaryView ) {
16- let Some ( file) =
17- binaryninja:: interaction:: get_open_filename_input ( "Select a .svd file" , "*.svd" )
18- else {
102+ let mut form = Form :: new ( "Load SVD File" ) ;
103+ let mut load_settings = LoadSettings :: from_view_settings ( view) ;
104+ form. add_field ( LoadFileField :: field ( ) ) ;
105+ form. add_field ( AddCommentsField :: field ( load_settings. add_comments ) ) ;
106+ form. add_field ( AddBitfieldsField :: field ( load_settings. add_bitfields ) ) ;
107+ form. add_field ( AddMemoryRegionsField :: field (
108+ load_settings. add_backing_regions ,
109+ ) ) ;
110+ if !form. prompt ( ) {
111+ return ;
112+ }
113+ let Some ( file_path) = LoadFileField :: from_form ( & form) else {
19114 return ;
20115 } ;
116+ load_settings. add_comments = AddCommentsField :: from_form ( & form) . unwrap_or ( true ) ;
117+ load_settings. add_bitfields = AddBitfieldsField :: from_form ( & form) . unwrap_or ( true ) ;
118+ load_settings. add_backing_regions = AddMemoryRegionsField :: from_form ( & form) . unwrap_or ( true ) ;
21119
22- let file_content = match std:: fs:: read_to_string ( & file ) {
120+ let file_content = match std:: fs:: read_to_string ( & file_path ) {
23121 Ok ( content) => content,
24122 Err ( e) => {
25- log:: error!( "Failed to read file: {}" , e) ;
123+ log:: error!( "Failed to read file: {:? }" , e) ;
26124 return ;
27125 }
28126 } ;
29127
30- match svd_parser:: parse ( & file_content) {
128+ // Disabling validation since vendors are lazy and don't follow the spec.
129+ let mut config = svd_parser:: Config :: default ( ) ;
130+ config. validate_level = ValidateLevel :: Disabled ;
131+ match svd_parser:: parse_with_config ( & file_content, & config) {
31132 Ok ( device) => {
32133 // We have a supported svd device. map it!
33- let load_settings = LoadSettings :: from_view_settings ( view) ;
34134 let address_size = view. address_size ( ) ;
35135 let mapper = DeviceMapper :: new ( load_settings, address_size, device) ;
36136 mapper. map_to_view ( view) ;
37137 view. update_analysis ( ) ;
38138 }
39139 Err ( e) => {
40- log:: error!( "Failed to parse SVD file: {}" , e) ;
140+ log:: error!( "Failed to parse SVD file: {:? }" , e) ;
41141 }
42142 }
43143 }
@@ -95,14 +195,16 @@ fn plugin_init() -> Result<(), ()> {
95195 return ;
96196 }
97197 } ;
98- match svd_parser:: parse ( & file_content) {
198+ let mut config = svd_parser:: Config :: default ( ) ;
199+ config. validate_level = ValidateLevel :: Disabled ;
200+ match svd_parser:: parse_with_config ( & file_content, & config) {
99201 Ok ( device) => {
100202 let address_size = view. address_size ( ) ;
101203 let mapper = DeviceMapper :: new ( load_settings, address_size, device) ;
102204 mapper. map_to_view ( & view) ;
103205 }
104206 Err ( e) => {
105- log:: error!( "Failed to parse SVD file: {}" , e) ;
207+ log:: error!( "Failed to parse SVD file: {:? }" , e) ;
106208 }
107209 }
108210 } ;
0 commit comments