130class Gpt_reader :
public Base_reader<Gpt_reader<DEV>, DEV>
132 using Device_type = DEV;
133 using Base = Base_reader<Gpt_reader<DEV>, Device_type>;
136 Gpt_reader(Device_type *dev)
137 : Base_reader<Gpt_reader<Device_type>, Device_type>(dev),
142 {
return _num_partitions; }
144 void read(Errand::Callback
const &callback)
override
147 Base::_callback = callback;
150 Base::_db = _header.inout_block();
151 Base::read_sectors(0, &Gpt_reader<Device_type>::get_gpt);
156 if (idx == 0 || idx > _num_partitions)
159 unsigned secsz = Base::_dev->sector_size();
160 auto *header = _header.template get<Gpt::Header const>(secsz);
163 _parray.template get<Gpt::Entry>((idx - 1) * header->entry_size);
168 render_guid(e->partition_guid, inf->
uuid);
171 std::u16string((
char16_t *)e->name,
sizeof(e->name) /
sizeof(e->name[0]));
172 inf->
name = name.substr(0, name.find((
char16_t) 0));
174 inf->
type = Gpt_part;
175 inf->
first = e->first;
177 inf->
flags = e->flags;
179 auto info = Dbg::info();
180 if (info.is_active())
182 info.printf(
"%3zu: %10lld %10lld %5gMiB [%.37s]\n",
183 idx, e->first, e->last,
184 (e->last - e->first + 1.0) * secsz / (1 << 20),
188 _Pragma(
"GCC diagnostic push");
189 _Pragma(
"GCC diagnostic ignored \"-Wdeprecated-declarations\"");
190 std::string pname = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,
char16_t>{}
191 .to_bytes(inf->
name);
192 _Pragma(
"GCC diagnostic pop");
193 info.printf(
" : [%s] Type: %s\n",
194 pname.c_str(), render_guid(e->type_guid, buf));
197 auto warn = Dbg::warn();
201 "Invalid settings of %3zu. Last lba before first lba. Will ignore.\n",
219 Base::invoke_callback();
224 unsigned secsz = Base::_dev->sector_size();
225 auto *header = _header.template get<Gpt::Header const>(secsz);
227 auto info = Dbg::info();
228 auto trace = Dbg::trace();
230 if (strncmp(header->signature,
"EFI PART", 8) != 0)
232 info.printf(
"No GUID partition header found.\n");
233 Base::invoke_callback();
239 info.printf(
"GUID partition header found with up to %d partitions.\n",
240 header->partition_array_size);
242 info.printf(
"GUID: %s\n", render_guid(header->disk_guid, buf));
243 trace.printf(
"Header positions: %llx (Backup: %llx)\n",
244 header->current_lba, header->backup_lba);
245 trace.printf(
"First + last: %llx and %llx\n",
246 header->first_lba, header->last_lba);
247 trace.printf(
"Partition table at %llx\n",
248 header->partition_array_lba);
249 trace.printf(
"Size of a partition entry: %d\n",
252 info.printf(
"GUID partition header found with %d partitions.\n",
253 header->partition_array_size);
258 l4_size_t arraysz = _num_partitions * header->entry_size;
259 l4_size_t numsec = (arraysz - 1 + secsz) / secsz;
264 trace.printf(
"Reading GPT table @ 0x%p\n", _parray.template get<void>(0));
266 Base::_db = _parray.inout_block();
267 Base::read_sectors(header->partition_array_lba, &Gpt_reader<DEV>::done_gpt);
279 Base::invoke_callback();
282 static char const *render_guid(
void const *guid_p,
char buf[])
284 auto *p =
static_cast<unsigned char const *
>(guid_p);
286 "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
287 p[3], p[2], p[1], p[0], p[5], p[4], p[7], p[6],
288 p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
312:
public Base_reader<typename std::conditional<std::is_class<DERIVED>::value,
313 DERIVED, Mbr_reader<DEV>>::type,
316 using Device_type = DEV;
318 typename std::conditional<std::is_class<DERIVED>::value, DERIVED,
319 Mbr_reader<DEV>>::type;
320 using Base = Base_reader<Derived_type, Device_type>;
330 Mbr_reader(Device_type *dev)
334 _partitions(Mbr::Primary_partitions),
341 return _num_partitions;
344 void read(Errand::Callback
const &callback)
override
347 Base::_callback = callback;
350 Base::_db = _header.inout_block();
351 Base::read_sectors(0, &Derived_type::get_mbr);
356 if (idx == 0 || idx > _num_partitions)
359 *inf = _partitions[idx - 1];
368 bool register_mbr_partition(Mbr::Entry
const *p,
l4_uint32_t disk_id,
371 _partitions.resize(n + 1);
373 auto info = Dbg::info();
376 if (p->type && p->lba_start <= p->lba_start + p->lba_num - 1)
379 snprintf(_partitions[n].uuid,
sizeof(_partitions[n].uuid),
"%08X-%02X",
381 _partitions[n].type = Mbr_part;
382 _partitions[n].first = _lba_offset_ext + p->lba_start;
383 _partitions[n].last = _lba_offset_ext + p->lba_start + p->lba_num - 1;
384 _partitions[n].flags = p->type;
386 info.printf(
"Partition %u, UUID=%s: start=%llu size=%zu, type=%x\n",
387 n + 1, _partitions[n].uuid, _partitions[n].first,
388 p->lba_num * Base::_dev->sector_size(), p->type);
390 if (p->type == Mbr::Partition_type::Extended && !_extended)
395 _partitions[n].type = Mbr_part;
396 _partitions[n].uuid[0] = 0;
397 _partitions[n].first = -1ULL;
398 _partitions[n].last = 0ULL;
399 _partitions[n].flags = 0ULL;
412 Base::invoke_callback();
416 _mbr = _header.template get<Mbr::Mbr const>(0);
418 auto info = Dbg::info();
420 if (_mbr->signature[0] != Mbr::Magic_lo
421 || _mbr->signature[1] != Mbr::Magic_hi)
423 info.printf(
"No MBR found.\n");
424 Base::invoke_callback();
428 info.printf(
"MBR found.\n");
430 for (
unsigned i = 0; i < Mbr::Primary_partitions; i++)
431 (
void)register_mbr_partition(&_mbr->partition[i], _mbr->disk_id, i);
433 _num_partitions = Mbr::Primary_partitions;
439 Base::_db = _ep.inout_block();
440 _lba_offset_ext += _extended->lba_start;
441 Base::read_sectors(_extended->lba_start, &Derived_type::get_ext);
444 Base::invoke_callback();
454 Base::invoke_callback();
458 auto *ext = _ep.template get<Mbr::Mbr const>(0);
460 auto info = Dbg::info();
461 if (ext->signature[0] != Mbr::Magic_lo
462 || ext->signature[1] != Mbr::Magic_hi)
464 info.printf(
"No extended MBR found.\n");
465 Base::invoke_callback();
469 info.printf(
"Extended MBR found at LBA %u.\n", _lba_offset_ext);
471 if (register_mbr_partition(&ext->partition[0], _mbr->disk_id,
476 if (next && _num_partitions < Max_partitions)
480 Base::_db = _ep.inout_block();
481 _lba_offset_ext = _extended->lba_start + next;
482 Base::read_sectors(_extended->lba_start + next,
483 &Derived_type::get_ext);
487 Base::invoke_callback();
491 Mbr::Mbr
const *_mbr;
493 std::vector<Partition_info> _partitions;
494 Mbr::Entry
const *_extended;
511class Labeling_reader :
public BASE
513 using Device_type = DEV;
517 Labeling_reader(Device_type *dev) : Base(dev), _cur(0)
520 void read(Errand::Callback
const &callback)
override
522 Base::read([=](){ label(callback); });
527 int ret = Base::get_partition(idx, inf);
530 if (inf->
name.empty())
532 auto it = _labels.find(idx);
533 if (it != _labels.end())
535 _Pragma(
"GCC diagnostic push");
536 _Pragma(
"GCC diagnostic ignored \"-Wdeprecated-declarations\"");
538 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,
540 .from_bytes(it->second);
541 _Pragma(
"GCC diagnostic pop");
551 for (; _cur < Base::table_size(); _cur++)
553 if (Base::get_partition(_cur + 1, info) ==
L4_EOK)
555 if (info->
type == Mbr_part
556 && info->
flags == Mbr::Partition_type::Linux)
565 void label(Errand::Callback
const &callback)
567 Base::_callback = callback;
571 Base::invoke_callback();
576 Base::_db = _sb.inout_block();
578 inf.
first + (Ext2::Superblock_offset / Base::_dev->sector_size()),
579 &Labeling_reader<Device_type, Base>::get_label);
589 Base::invoke_callback();
595 auto *sb = _sb.template get<Ext2::Superblock const>(
596 Ext2::Superblock_offset % Base::_dev->sector_size());
598 auto info = Dbg::info();
599 if (sb->magic == Ext2::Superblock_magic
600 && sb->major >= Ext2::Superblock_version)
602 std::string label = std::string(
603 reinterpret_cast<const char *
>(sb->name),
604 cxx::min(strlen(
reinterpret_cast<const char *
>(sb->name)),
606 label.erase(0, label.find_first_not_of(
" "));
607 label.erase(label.find_last_not_of(
" ") + 1);
608 info.printf(
"Found Ext2 superblock on partition %u, label=%s\n",
609 _cur + 1, label.c_str());
610 _labels[_cur + 1] = label;
613 info.printf(
"No label found for partition %u.\n", _cur + 1);
618 Base::invoke_callback();
624 Base::_db = _sb.inout_block();
626 inf.
first + (Ext2::Superblock_offset / Base::_dev->sector_size()),
627 &Labeling_reader<Device_type, Base>::get_label);
631 std::map<unsigned, std::string> _labels;
653class Partition_reader :
public Base_reader<Partition_reader<DEV>, DEV>
655 using Device_type = DEV;
656 using Base = Base_reader<Partition_reader<DEV>, Device_type>;
659 Partition_reader(Device_type *dev)
660 : Base_reader<Partition_reader<Device_type>, Device_type>(dev),
666 return _reader->table_size();
669 void read(Errand::Callback
const &callback)
override
671 Base::_callback = callback;
678 if (_reader->table_size() == 0)
683 cxx::make_ref_obj<Labeling_mbr_reader<Device_type>>(Base::_dev);
684 _reader->read([=](){ Base::invoke_callback();});
687 Base::invoke_callback();
693 return _reader->get_partition(idx, inf);