1 // compLoader.cxx - object file loader component. -*- C++ -*-
3 // Copyright (C) 1999, 2000 Red Hat.
4 // This file is part of SID and is licensed under the GPL.
5 // See the file COPYING.SID for conditions for redistribution.
9 #include <sidcomputil.h>
10 #include <sidattrutil.h>
11 #include <sidpinutil.h>
12 #include <sidbusutil.h>
13 #include <sidcpuutil.h>
15 #include <sidmiscutil.h>
41 using sid::host_int_1;
42 using sid::little_int_1;
43 using sid::host_int_4;
44 using sid::component_library;
45 using sid::COMPONENT_LIBRARY_MAGIC;
47 using sidutil::no_bus_component;
48 using sidutil::fixed_attribute_map_component;
49 using sidutil::fixed_pin_map_component;
50 using sidutil::fixed_accessor_map_component;
51 using sidutil::no_relation_component;
52 using sidutil::output_pin;
53 using sidutil::callback_pin;
54 using sidutil::string2stream;
55 using sidutil::stream2string;
56 using sidutil::make_attribute;
57 using sidutil::make_numeric_attribute;
58 using sidutil::parse_attribute;
59 using sidutil::std_error_string;
61 // ----------------------------------------------------------------------------
63 class generic_loader: public virtual component,
64 protected no_bus_component,
65 protected fixed_attribute_map_component,
66 protected fixed_pin_map_component,
67 protected fixed_accessor_map_component,
68 protected no_relation_component
71 callback_pin<generic_loader> doit_pin;
74 // entry point address
75 output_pin start_pc_pin;
76 // endianness as specified in ELF header.
77 // The value is one of sidutil::endian_*.
78 output_pin endian_pin;
80 // Signal this if something went wrong.
83 // loadable file names
88 bus* load_accessor_insn;
89 bus* load_accessor_data;
91 // The load pin was triggered.
92 virtual void load_it (host_int_4) = 0;
95 friend ostream& operator << (ostream& o, const generic_loader& it);
96 friend istream& operator >> (istream& i, generic_loader& it);
97 string save_state() { return make_attribute(*this); }
98 sid::component::status restore_state(const string& state)
99 { return parse_attribute(state, *this); }
103 doit_pin(this, & generic_loader::load_it),
105 load_file("/dev/null"),
106 load_accessor_insn(0),
107 load_accessor_data(0)
109 add_pin("load!", & this->doit_pin);
110 add_pin("start-pc-set", & this->start_pc_pin);
111 add_pin("endian-set", & this->endian_pin);
112 add_pin("error", & this->error_pin);
113 add_accessor("load-accessor-insn", & this->load_accessor_insn);
114 add_accessor("load-accessor-data", & this->load_accessor_data);
115 add_attribute("file", & this->load_file, "setting");
116 add_attribute("verbose?", & this->verbose_p, "setting");
117 add_attribute_virtual ("state-snapshot", this,
118 & generic_loader::save_state,
119 & generic_loader::restore_state);
125 operator << (ostream& out, const generic_loader& it)
127 out << "loader-state "
128 << string2stream(it.load_file) << " "
136 operator >> (istream& in, generic_loader& it)
140 if (coding == "loader-state")
142 in >> stream2string(it.load_file)
147 in.setstate(ios::badbit);
153 // ----------------------------------------------------------------------------
155 class elf_loader: public generic_loader
157 // static pointer to active instance (XXX: concurrency?)
158 static elf_loader* freeloader;
160 // callback function from C code in elfload.c
161 static int load_function(host_int_8 dest_addr, char* host_addr, host_int_8 file_offset, host_int_8 bytes, int insn_space);
162 static int verbose_function(char* s);
164 // stream for current file
167 void load_it (host_int_4)
169 if (this->load_accessor_insn == 0 || this->load_accessor_data == 0)
171 cerr << "loader: error - target accessors not configured!" << endl;
172 this->error_pin.drive (0);
178 cout << "loader: Reading program " << this->load_file << endl;
181 assert(elf_loader::freeloader == 0);
182 this->file = new ifstream(this->load_file.c_str(), ios::binary | ios::in);
183 if (! this->file->good())
185 cerr << "loader: error opening " << load_file << ": "
186 << std_error_string() << endl;
190 elf_loader::freeloader = this;
191 unsigned entry_point;
193 int success_p = readElfFile(& elf_loader::load_function,
194 & entry_point, & little_endian_p);
195 elf_loader::freeloader = 0;
199 // Tell anyone who's listening things we learned about the elf file.
200 this->start_pc_pin.drive((host_int_4) entry_point);
202 this->endian_pin.drive(sidutil::endian_little);
204 this->endian_pin.drive(sidutil::endian_big);
208 cerr << "loader: error loading " << load_file << endl;
209 this->error_pin.drive (0);
218 elf_loader* elf_loader::freeloader = 0;
222 elf_loader::load_function(host_int_8 dest_addr, char *host_addr, host_int_8 file_offset, host_int_8 bytes, int insn_space)
224 elf_loader& l = * elf_loader::freeloader;
225 string who = insn_space ? "instruction" : "data";
230 cout << "loader: reading "
231 << make_numeric_attribute (bytes, ios::hex | ios::showbase)
232 << " bytes from file offset "
233 << make_numeric_attribute (file_offset, ios::hex | ios::showbase)
234 << " into target " << who << " memory at "
235 << make_numeric_attribute ((void *)dest_addr, ios::hex | ios::showbase)
239 ifstream& f = * l.file;
243 b = l.load_accessor_insn;
245 b = l.load_accessor_data;
248 // go to proper offset in file
249 f.seekg(file_offset);
251 // fetch lots of characters
252 for (int n = 0; n < bytes; n++)
258 cerr << "loader: error reading byte " << file_offset+n
259 << " from file " << l.load_file << endl;
263 if (host_addr) // read into host buffer
265 // cerr << "H:" << (void*)host_addr << ":" << hex << (int)c << dec << endl;
268 else // read into target memory
270 host_int_8 a = dest_addr++;
271 little_int_1 data = c;
276 do // loop while memory getting ready
278 s = b->write(addr, data);
279 } while (s == bus::delayed);
281 if (s != bus::ok) // abort on error
283 cerr << "loader: write to " << who << " accessor failed at address "
284 << make_numeric_attribute (addr, ios::hex | ios::showbase)
290 // cerr << "T:" << addr << ":" << data << endl;
296 // ----------------------------------------------------------------------------
300 compLoaderListTypes()
302 vector<string> types;
303 types.push_back("sw-load-elf");
309 compLoaderCreate(const string& typeName)
311 if (typeName == "sw-load-elf")
312 return new elf_loader();
319 compLoaderDelete(component* c)
321 delete dynamic_cast<elf_loader*>(c);
325 extern const component_library loader_component_library;
327 const component_library loader_component_library DLLEXPORT =
329 COMPONENT_LIBRARY_MAGIC,
330 & compLoaderListTypes,