代码改变世界

使用dd生成二进制bin文件脚本

2024-10-16 11:26  Tanwheey  阅读(6)  评论(0编辑  收藏  举报
    def set_copy_bin_file(self, format_type=0, source_range_entry_list=[[0, 0, 0, 0, 0]]):
        """ 生成Copy的源起始的bin文件
        Args:
            format_type: int,copy format类型, 0/1
            source_range_entry_list: List,copy的源起始entry列表,每个entry包含一个List:[slba、nlb、elbst_eilbrt、elbat、elbatm]
        Returns:
            out_file文件
        """
        out_file = f'{str(time.time())}.bin'
        count = len(source_range_entry_list)
        if format_type == 0:
            cmd = f'dd if=/dev/zero of={out_file} bs=1 count={count * 32} conv=notrunc'
            stdout, stderr = self.linux_exec(cmd, get_pty=True)
            assert f'{count * 32} bytes' in stdout, '命令下发失败'

            for i in range(count):
                modify_data = (source_range_entry_list[i][0] << 64) + (source_range_entry_list[i][1] << 128) + (source_range_entry_list[i][2] << 192) + (source_range_entry_list[i][3] << 224) + (source_range_entry_list[i][4] << 240)
                start_byte = i * 32
                self.set_dd_modify_file(start_byte=start_byte, file=out_file, modify_data=modify_data)

        else:
            cmd = f'dd if=/dev/zero of={out_file} bs=1 count={count * 40} conv=notrunc'
            stdout, stderr = self.linux_exec(cmd, get_pty=True)
            assert f'{count * 40} bytes' in stdout, '命令下发失败'

            for i in range(count):
                modify_data = (source_range_entry_list[i][0] << 64) + (source_range_entry_list[i][1] << 128) + (
                            source_range_entry_list[i][2] << 208) + (source_range_entry_list[i][3] << 288) + (
                                          source_range_entry_list[i][4] << 304)
                start_byte = i * 40
                self.set_dd_modify_file(start_byte=start_byte, file=out_file, modify_data=modify_data)

        return out_file

    def set_copy(self, sn=None, dev=None, source_range_entry_list=[[0, 0, 0, 0, 0]], **kwargs):
        """ nvme io-passthru命令下发copy
        Args:
            self               :类对象
            sn                 :盘片sn,字符串
            dev                :盘符,字符串
            namespace_id       :desired namespace, -n <NUM>
            ## datasize           :data I/O length (bytes)
            # ref_storage_tag    :command dword 2 & dword3 & dword14 value,和PI相关,指定LBST和ILBRT,-2 <NUM>、-3 <NUM>、-8 <NUM>
            sdlba              :command dword 10 & dword11 value,64-bit addr of first block to access,-4 <NUM>、-5 <NUM>
            range_count        :int, number of ranges(NR), base 0, dword12.bit07:00 -6 <NUM>
            descriptor_format  :int, Descriptor Format, dword12.bit11:08, 0-Format0、 1-Format1、 all others-invalid -6 <NUM>
            prinfor            :int, PI Read, PI Action and Check field, dword12.bit15:12 -6 <NUM>
            dirtype            :int, Directive Type, dword12.bit23:20 -6 <NUM>
            stcw               :int, Storage Check Write, dword12.bit24 -6 <NUM>
            prinfow            :int, PI Write, PI Action and Check field, dword12.bit29:26 -6 <NUM>
            fua                :int, force unit access, force device to commit data before command completes, dword12.bit30 -6 <NUM>
            lr                 :int, limited retry, limit media access attempts, dword12.bit31 -6 <NUM>
            input_file         :write/send file (default stdin), Copy Format0/1 Source Range Entrys, -i <FILE>
            dirspec            :directive specific, dword13.bit31:16 -7 <NUM>
            # app_tag            :command dword 15 bit15:00 value,和PI相关,指定LBAT,-9 <NUM>
            # app_mask           :command dword 15 bit31:16 value,和PI相关,指定LBATM,-9 <NUM>
            timeout            :timeout value, in milliseconds -t <NUM>
            kwargs             :不定参数,字典
        Returns:
            True布尔型
        """
        namespace_id = kwargs.get('namespace_id')
        sdlba = kwargs.get('sdlba')
        range_count = kwargs.get('range_count')
        descriptor_format = kwargs.get('descriptor_format')
        limited_retry = kwargs.get('limited_retry')
        force_access = kwargs.get('force_access')
        prinfor = kwargs.get('prinfor')
        dirtype = kwargs.get('dirtype')
        dirspec = kwargs.get('dirspec')
        # stcw = kwargs.get('stcw')
        prinfow = kwargs.get('prinfow')
        fua = kwargs.get('fua')
        lr = kwargs.get('lr')
        # app_mask = kwargs.get('app_mask')
        # app_tag = kwargs.get('app_tag')

        cmd_str = '-o 0x19 '
        if namespace_id is not None:
            cmd_str += f' -n {namespace_id}'
        if sdlba is not None:
            if len(hex(sdlba)[2:]) <= 8:
                cmd_str += f' -4 {sdlba}'
            else:
                dword10 = int(hex(sdlba)[-8:], 16)
                dword11 = sdlba >> 32
                if dword10 == 0:
                    cmd_str += f' -5 {dword11}'
                cmd_str += f' -4 {dword10} -5 {dword11}'
        dword12 = 0
        if range_count is not None:
            dword12 += int(range_count)
        if descriptor_format is not None:
            dword12 += int(descriptor_format) << 8
        if prinfor is not None:
            dword12 += int(prinfor) << 12
        if dirtype is not None:
            dword12 += int(dirtype) << 20
        # if stcw is not None:
        #     dword12 += int(stcw) << 24
        if prinfow is not None:
            dword12 += int(prinfow) << 26
        if fua is not None:
            dword12 += int(fua) << 30
        if lr is not None:
            dword12 += int(lr) << 31
        if dword12 != 0:
            cmd_str += f' -6 {dword12}'
        if dirspec is not None:
            cmd_str += f' -7 {dirspec}'

        input_file = self.set_copy_bin_file(format_type=descriptor_format,
                                            source_range_entry_list=source_range_entry_list)
        cmd_str += f' -i {input_file} -l 512 -w'
        dev = dev if dev else self.get_dev_ctrl(sn)
        res, stderr = self.io_passthru(dev, *cmd_str)
        return res, stderr

        # self.rm_file(input_file)