{"id":2582,"date":"2018-01-14T20:53:36","date_gmt":"2018-01-14T11:53:36","guid":{"rendered":"https:\/\/www.naraeon.net\/?p=2582"},"modified":"2024-09-24T22:43:17","modified_gmt":"2024-09-24T13:43:17","slug":"physicaldrive-abstraction","status":"publish","type":"post","link":"https:\/\/www.naraeon.net\/en\/physicaldrive-abstraction\/","title":{"rendered":"Naraeon SSD Tools internals &#8211; 3. Physical drive abstraction"},"content":{"rendered":"<p><b>Necessity<\/b><\/p>\n<p>Physical drives have various features. From these features, <a href=\"https:\/\/github.com\/ebangin127\/naraeon-ssd\/blob\/master\/trunk\/WindowsFileAPI\/Device.PhysicalDrive.pas\">TPhysicalDrive<\/a>\u00a0abstracts some of them those are needed to Naraeon SSD Tools. Internally, the object just passes the request to right object. There are objects process these requests. Firstly, there is an object that issue adequate command to the bus directly(ATA, SCSI, NVMe, &#8230;).\u00a0 And there is another object that has functions can be done with other ioctls. Former one is\u00a0<a href=\"https:\/\/github.com\/ebangin127\/naraeon-ssd\/blob\/f3d3c6bed530dc6563f5bed37cfe912bfbaf866e\/trunk\/WindowsFileAPI\/Device.PhysicalDrive.Bus.pas\">TBusPhysicalDrive<\/a>, and latter one is\u00a0<a href=\"https:\/\/github.com\/ebangin127\/naraeon-ssd\/blob\/f3d3c6bed530dc6563f5bed37cfe912bfbaf866e\/trunk\/WindowsFileAPI\/Device.PhysicalDrive.OS.pas\">TOSPhysicalDrive<\/a>.<\/p>\n<p><strong>Why interface?<\/strong><\/p>\n<p>In whole code, this object is used in IPhysicalDrive interface form, not TPhysicalDrive object form. Because in Delphi,\u00a0<a href=\"http:\/\/docwiki.embarcadero.com\/RADStudio\/Tokyo\/en\/Using_Interfaces\">inteface has reference counting based resource management feature<\/a>. This project uses interface only by that reason.<\/p>\n<p>But when not directly inherited\u00a0<a href=\"http:\/\/docwiki.embarcadero.com\/RADStudio\/Tokyo\/en\/TInterfacedObject\">TInterfacedObject<\/a>, reference counting feature must be implemented manually. And Delphi doesn&#8217;t support multiple inheritance. So I just copied+pasted the implementation from VCL source. Delphi users have rights to use VCL source legally. When implementing the same thing in other languages, just use smart pointers.<\/p>\n<p><strong>Commands that can be issued only with low-level ioctls: <a href=\"https:\/\/github.com\/ebangin127\/naraeon-ssd\/blob\/f3d3c6bed530dc6563f5bed37cfe912bfbaf866e\/trunk\/WindowsFileAPI\/Device.PhysicalDrive.Bus.pas\">TBusPhysicalDrive<\/a><\/strong><\/p>\n<p>TBusPhysicalDrive gets basic things of the drive. For example, model, serial, capacity, SMART values, SATA speed, etc. In fact, <a href=\"https:\/\/github.com\/ebangin127\/naraeon-ssd\/blob\/master\/trunk\/WindowsFileAPI\/CommandSet.pas\">TCommandSet<\/a>\u00a0issues the command and\u00a0<a href=\"https:\/\/github.com\/ebangin127\/naraeon-ssd\/blob\/master\/trunk\/WindowsFileAPI\/BufferInterpreter.pas\">TBufferInterpreter<\/a>\u00a0translates the buffer into readable form. But information about them will be written in future.<\/p>\n<div id=\"attachment_2593\" style=\"width: 450px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.naraeon.net\/physicaldrive-abstraction\/busidentify\/#main\" rel=\"attachment wp-att-2593\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2593\" class=\"wp-image-2593 size-full\" src=\"https:\/\/www.naraeon.net\/wp-content\/uploads\/2018\/01\/wsi-imageoptim-busidentify.png\" alt=\"\" width=\"440\" height=\"326\" srcset=\"https:\/\/www.naraeon.net\/wp-content\/uploads\/2018\/01\/wsi-imageoptim-busidentify.png 440w, https:\/\/www.naraeon.net\/wp-content\/uploads\/2018\/01\/wsi-imageoptim-busidentify-300x222.png 300w\" sizes=\"auto, (max-width: 440px) 100vw, 440px\" \/><\/a><\/p>\n<p id=\"caption-attachment-2593\" class=\"wp-caption-text\">Information from Identify command<\/p>\n<\/div>\n<div id=\"attachment_2594\" style=\"width: 441px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.naraeon.net\/physicaldrive-abstraction\/bussmart\/#main\" rel=\"attachment wp-att-2594\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2594\" class=\"wp-image-2594 size-full\" src=\"https:\/\/www.naraeon.net\/wp-content\/uploads\/2018\/01\/wsi-imageoptim-bussmart.jpg\" alt=\"\" width=\"431\" height=\"326\" srcset=\"https:\/\/www.naraeon.net\/wp-content\/uploads\/2018\/01\/wsi-imageoptim-bussmart.jpg 431w, https:\/\/www.naraeon.net\/wp-content\/uploads\/2018\/01\/wsi-imageoptim-bussmart-300x227.jpg 300w\" sizes=\"auto, (max-width: 431px) 100vw, 431px\" \/><\/a><\/p>\n<p id=\"caption-attachment-2594\" class=\"wp-caption-text\">Information from SMART command<\/p>\n<\/div>\n<p><strong>When low-level passthrough isn&#8217;t neccessary: <a href=\"https:\/\/github.com\/ebangin127\/naraeon-ssd\/blob\/f3d3c6bed530dc6563f5bed37cfe912bfbaf866e\/trunk\/WindowsFileAPI\/Device.PhysicalDrive.OS.pas\">TOSPhysicalDrive<\/a><\/strong><\/p>\n<p>TOSPhysicalDrive gets information that can be got from simple OS request. Like availability, user size, partition list, NCQ availability. OS can quickly and easily give us these information.<\/p>\n<p><a href=\"https:\/\/github.com\/ebangin127\/naraeon-ssd\/blob\/master\/trunk\/WindowsFileAPI\/Getter.PhysicalDrive.DriveAvailability.pas\">TDriveAvailabilityGetter<\/a>\u00a0gets availability of the drive. This validates the handle and use\u00a0<a href=\"https:\/\/msdn.microsoft.com\/library\/windows\/desktop\/aa363404(v=vs.85).aspx\">IOCTL_STORAGE_CHECK_VERIFY<\/a>\u00a0ioctl code to further check.<\/p>\n<p><a href=\"https:\/\/github.com\/ebangin127\/naraeon-ssd\/blob\/master\/trunk\/WindowsFileAPI\/Getter.PhysicalDrive.DiskGeometry.pas\">TDiskGeometryGetter<\/a> gets size of the drive. Done with\u00a0<a href=\"https:\/\/msdn.microsoft.com\/library\/windows\/desktop\/aa365171(v=vs.85).aspx\">IOCTL_DISK_GET_DRIVE_GEOMETRY_EX<\/a>\u00a0ioctl code.<\/p>\n<p><a href=\"https:\/\/github.com\/ebangin127\/naraeon-ssd\/blob\/master\/trunk\/WindowsFileAPI\/Getter.PhysicalDrive.PartitionList.pas\">TPartitionListGetter<\/a> gets partition list of the drive. Firstly get fixed drives with <a href=\"https:\/\/msdn.microsoft.com\/library\/windows\/desktop\/aa364975%28v=vs.85%29.aspx?f=255&amp;MSPPError=-2147217396\">GetLogicalDriveStrings<\/a>, and find partitions in the drive with the\u00a0<a href=\"https:\/\/msdn.microsoft.com\/library\/windows\/desktop\/aa365194(v=vs.85).aspx\">Extent<\/a>\u00a0of each partition.<\/p>\n<p><a href=\"https:\/\/msdn.microsoft.com\/library\/windows\/desktop\/aa365171(v=vs.85).aspx\">TNCQAvailabilityGetter<\/a> gets NCQ availability of the drive. It uses\u00a0<a href=\"https:\/\/msdn.microsoft.com\/library\/windows\/desktop\/ff800830%28v=vs.85%29.aspx?f=255&amp;MSPPError=-2147217396\">IOCTL_STORAGE_QUERY_PROPERTY<\/a>\u00a0ioctl code. Internally it uses BusType and CommandQueueing to decide whether NCQ is available or not. The condition is got from test result of drivers at that time.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Necessity Physical drives have various features. From these features, TPhysicalDrive\u00a0abstracts some of them those are needed to Naraeon SSD Tools. Internally, the object just passes the request to right object. There are objects process these requests. Firstly, there is an object that issue adequate command to the bus directly(ATA, SCSI, NVMe, &#8230;).\u00a0 And there is [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[300],"tags":[306,304,59,58,307,305,303,302],"class_list":["post-2582","post","type-post","status-publish","format-standard","hentry","category-ssd-tool-internals","tag-ata","tag-ioctl","tag-nvm-express","tag-nvme","tag-sat","tag-sata","tag-windows","tag-302"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"en","enabled_languages":["kr","en"],"languages":{"kr":{"title":true,"content":true,"excerpt":false},"en":{"title":true,"content":true,"excerpt":false}}},"_links":{"self":[{"href":"https:\/\/www.naraeon.net\/en\/wp-json\/wp\/v2\/posts\/2582","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.naraeon.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.naraeon.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.naraeon.net\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.naraeon.net\/en\/wp-json\/wp\/v2\/comments?post=2582"}],"version-history":[{"count":8,"href":"https:\/\/www.naraeon.net\/en\/wp-json\/wp\/v2\/posts\/2582\/revisions"}],"predecessor-version":[{"id":2617,"href":"https:\/\/www.naraeon.net\/en\/wp-json\/wp\/v2\/posts\/2582\/revisions\/2617"}],"wp:attachment":[{"href":"https:\/\/www.naraeon.net\/en\/wp-json\/wp\/v2\/media?parent=2582"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.naraeon.net\/en\/wp-json\/wp\/v2\/categories?post=2582"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.naraeon.net\/en\/wp-json\/wp\/v2\/tags?post=2582"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}