alynna

Untitled

Jun 18th, 2020
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.63 KB | None | 0 0
  1. /* Partition parser main routines (partparse.c)
  2.    (C) 2020 Alynna Trypnotk, license APL
  3.  */
  4.  
  5.  
  6. // Configuration section
  7. #define DEVICE_NAME     "sagasd.device"             // Exec device name
  8. #define DEVICE_TEMPLATE "SD@P$"                     // DOS device template:  @=unit number, $=Partition #
  9. #define LBA_HEADS       16                          // Should match your driver, or LBA spec
  10. #define LBA_SECTORS     64                          // Should match your driver, or LBA spec
  11.  
  12. // For porting to other drivers:  Put a routine that reads 512 bytes from a disk block into a buffer here.
  13. #define READBLOCK(block, buffer) sdcmd_read_blocks(&sdu->sdu_SDCmd, block, buffer, 512);
  14. // You also probably have to change all the SAGASDBase references to your own class.
  15.  
  16. #include <dos/filehandler.h>
  17. #include <exec/libraries.h>
  18. #include <exec/devices.h>
  19. #include <exec/types.h>
  20. #include <exec/io.h>
  21. #include <libraries/expansion.h>
  22. #include <proto/exec.h>
  23. #include <proto/disk.h>
  24. #include <proto/expansion.h>
  25. #include <dos/filehandler.h>
  26. #include "partparser.h"
  27.  
  28. static BOOL ParseRDB(struct SAGASDBase * SAGASDBase, ULONG unit, UBYTE data[], struct DosPacket *dos, UBYTE blk) {
  29.     struct Library *SysBase = SAGASDBase->sd_ExecBase;
  30.     struct SAGASDUnit *sdu = &SAGASDBase->sd_Unit[unit];
  31.     UBYTE i=0;
  32.     if (db(0x1c) == 0xffffffff) return FALSE;   // RDB without partitions
  33.    
  34.     while (TRUE) {
  35.         sderr = READBLOCK(blk, data);
  36.         if (sderr) return FALSE;
  37.        
  38.         if ((ULONG)data[0x0x14] & (1<<2)) continue;     // Skip drives marked no automount
  39.         data[0x24+db(0x24)+1] = (UBYTE)0;               // BSTR to string      
  40.         // Finish naming unit
  41.         for (j=0; db(0x24+j) == 0;, j++)
  42.             if (db(0x24+j) == '$') dos->dp_DosName[j] = 48+i;
  43.             else dos->dp_DosName[j] = db(0x24+j);
  44.         dos->dp_DosName[j+1] = 0;
  45.        
  46.         // Fill in DosPacket
  47.         dos->dp_ExecName = DEVICE_NAME;                     // Exec device
  48.         dos->dp_Flags |= dl(0x20);                          // Merge requested DosFlags with ones on partition
  49.         memcpy(&dos->env,&data[0x80],sizeof(DosEnvec)); // Copy partitions DosEnvec into our packet.
  50.         // Add DevNode with a ConfigDev
  51.         struct DeviceNode *devnode = MakeDosNode(dos);
  52.         if (devnode) {
  53.             struct ConfigDev *configdev = AllocConfigDev();
  54.             configdev->cd_Flags = 0x9;
  55.             configdev->cd_Driver = SAGASDBase.sd_Device;
  56.             AddBootNode(d, 0 & ADNF_STARTPROC, devnode, configdev);
  57.         }
  58.         // If Next = -1 then no more partitions ...
  59.         if (dl(0x10) == 0xffffffff) break;
  60.             else blk = dl(0x10);  // else its the next block.
  61.         i++;
  62.     }
  63. }
  64.  
  65. static BOOL ParseMBR(struct SAGASDBase * SAGASDBase, ULONG unit, UBYTE data[], struct DosPacket *dos, UBYTE parttype) {
  66.     struct Library *SysBase = SAGASDBase->sd_ExecBase;
  67.     struct SAGASDUnit *sdu = &SAGASDBase->sd_Unit[unit];
  68.    
  69.     // Get partition data .. not going to bother with extended partitions for now.  Maybe later.
  70.     MBR part[4];
  71.     part[0] = *(char[16] *)data[0x1be];
  72.     part[1] = *(char[16] *)data[0x1ce];
  73.     part[2] = *(char[16] *)data[0x1de];
  74.     part[3] = *(char[16] *)data[0x1ee];
  75.    
  76.     struct Library *ExpansionBase = TaggedOpenLibrary(TAGGEDOPEN_EXPANSION);
  77.    
  78.     // Read all 4 partitions
  79.     for(UBYTE j=0; j<4; j++) {
  80.         if (part[j].status) {  // Has partition ID?
  81.         if ((ULONG)(char[3](h1)) & ISLBA) { // With LBA we define our own values for sectors/heads
  82.                 dos->dp_BlocksPerTrack =    (IPTR) LBA_SECTORS;
  83.                 dos->dp_Surfaces =          (IPTR) LBA_HEADS;
  84.                 dos->dp_LowCyl =            (IPTR) CYLINDER(part[j].lbas);
  85.                 dos->dp_HighCyl =           (IPTR) CYLINDER(part[j].lbac) + dos->dp_LowCyl;            
  86.             } else {    // For CHS we should base it on whats in the partition table
  87.                 dos->dp_BlocksPerTrack =    (IPTR) CHS_HISECT(j)+1;
  88.                 dos->dp_Surfaces =          (IPTR) CHS_HIHEAD(j)+1;
  89.                 dos->dp_LowCyl =            (IPTR) CHS_LOCYLN(j);
  90.                 dos->dp_HighCyl =           (IPTR) CHS_HICYLN(j);
  91.             }
  92.             dos->dp_DosType =           (IPTR) DosTypeOf(part[j].type);  // Make MBR type into Amiga type
  93.             dos->dp_SectorsPerBlock =   (IPTR) 1;               // All the rest of this stuff pretty standard
  94.             dos->dp_SizeBlock =         (IPTR) 512;
  95.             dos->dp_PreAlloc =          (IPTR) 0;
  96.             dos->dp_Interleave =        (IPTR) 0;
  97.             dos->dp_SecOrg =            (IPTR) 0;
  98.             dos->dp_NumBuffers =        (IPTR) MEMF_PUBLIC;
  99.             dos->dp_Mask =              (IPTR) 0xFFFFFFFE;
  100.             dos->dp_BootPri =           (IPTR) -128;
  101.             dos->dp_Baud =              (IPTR) 0;
  102.             dos->dp_Control =           (IPTR) 0;
  103.             dos->dp_BootBlocks =        (IPTR) 2;
  104.             // Finish naming unit
  105.             for (j=0; (UBYTE)dos->dp_DosName[j] == 0;, j++)
  106.                 if (dos->dp_DosName[i] == '$') dos->dp_DosName[j] = 48+i;
  107.             dos->dp_DosName[j+1] = 0;
  108.             struct DeviceNode *devnode = MakeDosNode(dos);
  109.             if (devnode) {
  110.                 struct ConfigDev *configdev = AllocConfigDev();
  111.                 // Fill in DosPacket
  112.                 dos->dp_ExecName = DEVICE_NAME;                     // Exec device
  113.                 dos->dp_Flags |= dl(0x20);                  // Merge requested DosFlags with ones on partition
  114.                 configdev->cd_Flags = 0x9;
  115.                 configdev->cd_Driver = SAGASDBase.sd_Device;
  116.                 // status & 0x80 = AmigaOS should presume its bootable
  117.                 // HaX, if you have in your partition table 0x82 as the status (first byte), it will give it a boot priority of 2.  It should still be valid to other OSes.
  118.                 AddBootNode((part[j].status & 0x80 ? (part[j].status & 0x7f)-j : -128), ADNF_STARTPROC, devnode, configdev);
  119.             }
  120.         }
  121.     }
  122.     CloseLibrary(ExpansionBase);
  123. }
  124.  
  125. static BOOL Part2DOSList(struct SAGASDBase * SAGASDBase, ULONG unit, UBYTE data[], ULONG flags, struct DosPacket *dos) {
  126.     struct Library *SysBase = SAGASDBase->sd_ExecBase;
  127.     struct SAGASDUnit *sdu = &SAGASDBase->sd_Unit[unit];
  128.  
  129.     // Set up stuff we already know.    
  130.     dos.dp_DosName = (IPTR)DEVICE_TEMPLATE;
  131.     dos.dp_ExecName = (IPTR)DEVICE_NAME;
  132.     dos.dp_Unit = unit;
  133.     dos.dp_Flags = 0;
  134.  
  135.     // Set the unit number in the template
  136.     for (UBYTE i=0; (UBYTE)dos.dp_DosName[i] == 0;, i++)
  137.         if (dos.dp_DosNamet[i] == '@') dos.dp_Unit[i] = 48+unit;
  138.    
  139.     sderr = READBLK(0, data);
  140.     if (sderr) return FALSE;
  141.  
  142.     if (dw(0x1fe) == 0x55aa) { // Some kind of MBR
  143.         if (dw(0x1da) == 0x0000 && (dw(0x1bc) == 0x0000 || dw(0x1bc) == 0x5a5a)
  144.             if (*(char[6])(data[0x02]) == "NEWLDR")
  145.                 return ParseMBR(SAGASDBase, unit, data[], dos, 2); // NEWLDR MBR
  146.             else
  147.                 return ParseMBR(SAGASDBase, unit, data[], dos, 1); // Modern MBR
  148.         else
  149.             return ParseMBR(SAGASDBase, unit, data[], dos, 0); // Old MBR
  150.     } else {
  151.         for (j=0; j<16, j++) { // RDB Seek
  152.             sderr = READBLOCK(j, data);
  153.             if ((char[4])data[0] == "RDSK") break;
  154.         }
  155.     }
  156.     if (j == 16)
  157.         return FALSE;   // No RDB found
  158.     else
  159.         return ParseRDSK(struct SAGASDBase, unit, data[], dos, j) // Rigid disk block
  160. }
  161.  
  162. static BOOL MkDosDevices(struct SAGASDBase * SAGASDBase, UBYTE unit, ULONG flags) {
  163.     // Allocate memory for essential structs
  164.     char data[512];
  165.     struct DosPacket dos;
  166.     // Start processing
  167.     return Part2DosList(SAGASDBase, unit, data, flags, dos);
  168. }
Add Comment
Please, Sign In to add comment