void write_segments (FILE* f, segtable* st, seq* target, seq* query) { u32 ix; segment* seg; static char* tName, *qName; static unspos tStart, qStart; seqpartition* tSp = &target->partition; seqpartition* qSp = &query->partition; partition* part; for (ix=0,seg=st->seg ; ix<st->len ; ix++,seg++) { if (tSp->p == NULL) // target is not partitioned { tName = (target->useFullNames)? target->header : target->shortHeader; if ((tName == NULL) || (tName[0] == 0)) tName = "target"; tStart = seg->pos1; } else // target is partitioned { part = lookup_partition (target, seg->pos1); tName = &tSp->pool[part->header]; tStart = seg->pos1 - (part->sepPos + 1); } if (qSp->p == NULL) // query is not partitioned { qName = (query->useFullNames)? query->header : query->shortHeader; if ((qName == NULL) || (qName[0] == 0)) qName = "query"; qStart = seg->pos2; } else // query is partitioned { part = lookup_partition (query, seg->pos2); qName = &qSp->pool[part->header]; qStart = seg->pos2 - (part->sepPos + 1); } //ии seg->id is supposed to be the strand, but apparently isn't //ии it's an rcf value fprintf (f, "[%d]" " %s " unsposFmt " " unsposFmt " %s " unsposFmt " " unsposFmt " %c " scoreFmtSimple "\n", ix, tName, tStart+1, tStart+seg->length, qName, qStart+1, qStart+seg->length, seg->id, seg->s); } }
static void print_query_quals (FILE* f, seq* seq2, unspos pos2, unspos length, int softMasked) { seqpartition* sp2 = &seq2->partition; partition* part; u8* s2 = seq2->vq + pos2; u8* ss2; unspos offset2, start2, end2; unspos startLoc2; unspos seq2Len, seq2True; unspos ix; ////////// // figure out position offsets, etc. ////////// if (sp2->p == NULL) // sequence 2 is not partitioned { offset2 = 0; startLoc2 = seq2->startLoc; seq2Len = seq2->len; seq2True = seq2->trueLen; } else // sequence 2 is partitioned { part = lookup_partition (seq2, pos2); offset2 = part->sepBefore + 1; startLoc2 = part->startLoc; seq2Len = part->sepAfter - offset2; seq2True = part->trueLen; } ////////// // print qual (qualities from sequence 2) ////////// start2 = pos2 - offset2 + startLoc2; end2 = start2-1 + length; if ((softMasked) && (start2 > 1)) { ss2 = seq2->vq + pos2 - (start2-1); for (ix=0 ; ix<start2-1 ; ix++) fprintf (f, "%c", ss2[ix]); } for (ix=0 ; ix<length ; ix++) fprintf (f, "%c", s2[ix]); if ((softMasked) && (end2 < seq2True)) { for (ix=length ; ix<seq2True - (start2-1) ; ix++) fprintf (f, "%c", s2[ix]); } }
void print_masking_interval_3 (unspos beg, unspos end, void* info) { FILE* f = ((pmiInfo*) info)->f; seq* _seq = ((pmiInfo*) info)->seq; seqpartition* sp = &_seq->partition; partition* part; char* name; unspos offset; // figure out position offsets and names if (sp->p == NULL) // sequence 1 is not partitioned { name = (_seq->useFullNames)? _seq->header : _seq->shortHeader; if ((name == NULL) || (name[0] == 0)) name = "seq1"; offset = 0; } else // sequence 1 is partitioned { part = lookup_partition (_seq, beg-1); name = &sp->pool[part->header]; offset = part->sepBefore + 1; } beg += _seq->startLoc - offset - 1; end += _seq->startLoc - offset - 1; // print the interval fprintf (f, "%s " unsposFmt " " unsposFmt "\n", name, beg, end); }
void init_ext2(t_ext2 *ext2,t_device_desc* device_desc) { t_group_block* group_block; ext2->device_desc=device_desc; ext2->superblock=kmalloc(sizeof(t_superblock)); ext2->partition_start_sector=lookup_partition(ext2,1); read_superblock(ext2); //ext2->root_dir_inode=kmalloc(sizeof(t_inode)); //read_root_dir_inode(ext2); ext2->device_desc=device_desc; }
void print_sam_match (FILE* f, seq* seq1, unspos pos1, seq* seq2, unspos pos2, unspos length, arg_dont_complain(score s), int softMasked, char* rgTags) { seqpartition* sp1 = &seq1->partition; seqpartition* sp2 = &seq2->partition; partition* part; char* name1, *name2; unspos offset1, offset2, start1, start2, end2; unspos startLoc1, startLoc2; unspos seq2Len, seq2True; int flag; char maskCh; unspos preMask, postMask, tmp; if (seq1->revCompFlags != rcf_forward) suicide ("attempt to print - strand or complement for sequence 1 in print_sam_match"); ////////// // figure out position offsets and names ////////// if (sp1->p == NULL) // sequence 1 is not partitioned { name1 = (seq1->useFullNames)? seq1->header : seq1->shortHeader; if ((name1 == NULL) || (name1[0] == 0)) name1 = "seq1"; offset1 = 0; startLoc1 = seq1->startLoc; } else // sequence 1 is partitioned { part = lookup_partition (seq1, pos1); name1 = &sp1->pool[part->header]; offset1 = part->sepBefore + 1; startLoc1 = part->startLoc; } if (sp2->p == NULL) // sequence 2 is not partitioned { name2 = (seq2->useFullNames)? seq2->header : seq2->shortHeader; if ((name2 == NULL) || (name2[0] == 0)) name2 = "seq2"; offset2 = 0; seq2Len = seq2->len; seq2True = seq2->trueLen; startLoc2 = seq2->startLoc; } else // sequence 2 is partitioned { part = lookup_partition (seq2, pos2); name2 = &sp2->pool[part->header]; offset2 = part->sepBefore + 1; seq2Len = part->sepAfter - offset2; seq2True = part->trueLen; startLoc2 = part->startLoc; } ////////// // print sam line (field names indicate below are per sam spec) ////////// start1 = pos1 - offset1 + startLoc1; if ((seq2->revCompFlags & rcf_rev) == 0) { start2 = pos2 - offset2 + startLoc2; end2 = start2-1 + length; flag = 0; } else { start2 = startLoc2 + offset2 + (seq2Len - pos2) - length; end2 = startLoc2 + offset2 + (seq2Len - pos2) - 1; flag = BAM_FREVERSE; } // print qname, flag, rname, pos and mapq (field names per sam spec) fprintf (f, "%s\t%d\t%s\t" unsposFmt "\t%d\t", name2, flag, name1, start1, 255); // print cigar maskCh = (softMasked)? 'S' : 'H'; preMask = postMask = 0; if (start2 > 1) preMask = start2 - 1; if (end2 < seq2True) postMask = seq2True - end2; if ((seq2->revCompFlags & rcf_rev) != 0) { tmp = preMask; preMask = postMask; postMask = tmp; } if (preMask != 0) fprintf (f, unsposFmt "%c", preMask, maskCh); fprintf (f, unsposFmt "M", length); if (postMask != 0) fprintf (f, unsposFmt "%c", postMask, maskCh); // print mrnm, mpos, and isize fprintf (f, "\t%s\t%d\t%d\t", "*", 0, 0); // print seq (data from sequence 2) print_query_bases (f, seq2, pos2, length, softMasked); // print qual (if we have no qual data, we print "*") if (seq2->vq == NULL) fprintf (f, "\t%s", "*"); else { fprintf (f, "\t"); print_query_quals (f, seq2, pos2, length, softMasked); } // print rgTags if (rgTags != NULL) fprintf (f, "\t%s", rgTags); fprintf (f, "\n"); }
void print_sam_align (FILE* f, seq* seq1, unspos beg1, unspos end1, seq* seq2, unspos beg2, unspos end2, editscript* script, arg_dont_complain(score s), int softMasked, char* rgTags) { seqpartition* sp1 = &seq1->partition; seqpartition* sp2 = &seq2->partition; partition* part; unspos height, width, i, j, prevI, prevJ, run; u32 opIx; unspos len2; char* name1, *name2; unspos offset1, offset2, start1, start2; unspos startLoc1, startLoc2; unspos seq2Len, seq2True; int flag; char maskCh; unspos preMask, postMask, tmp; if (seq1->revCompFlags != rcf_forward) suicide ("attempt to print - strand or complement for sequence 1 in print_sam_align"); beg1++; // (internally, we want origin 1, inclusive) beg2++; height = end1 - beg1 + 1; len2 = width = end2 - beg2 + 1; ////////// // figure out position offsets and names ////////// if (sp1->p == NULL) // sequence 1 is not partitioned { name1 = (seq1->useFullNames)? seq1->header : seq1->shortHeader; if ((name1 == NULL) || (name1[0] == 0)) name1 = "seq1"; offset1 = 0; startLoc1 = seq1->startLoc; } else // sequence 1 is partitioned { part = lookup_partition (seq1, beg1-1); name1 = &sp1->pool[part->header]; offset1 = part->sepBefore + 1; startLoc1 = part->startLoc; } if (sp2->p == NULL) // sequence 2 is not partitioned { name2 = (seq2->useFullNames)? seq2->header : seq2->shortHeader; if ((name2 == NULL) || (name2[0] == 0)) name2 = "seq2"; offset2 = 0; seq2Len = seq2->len; seq2True = seq2->trueLen; startLoc2 = seq2->startLoc; } else // sequence 2 is partitioned { part = lookup_partition (seq2, beg2-1); name2 = &sp2->pool[part->header]; offset2 = part->sepBefore + 1; seq2Len = part->sepAfter - offset2; seq2True = part->trueLen; startLoc2 = part->startLoc; } ////////// // print sam line (field names indicate below are per sam spec) ////////// start1 = beg1-1 - offset1 + startLoc1; if ((seq2->revCompFlags & rcf_rev) == 0) { start2 = beg2-1 - offset2 + startLoc2; end2 = start2-1 + len2; flag = 0; } else { start2 = startLoc2 + offset2 + (seq2Len - beg2) - (len2-1); end2 = startLoc2 + offset2 + (seq2Len - beg2); flag = BAM_FREVERSE; } // print qname, flag, rname, pos and mapq fprintf (f, "%s\t%d\t%s\t" unsposFmt "\t%d\t", name2, flag, name1, start1, 255); // print cigar maskCh = (softMasked)? 'S' : 'H'; preMask = postMask = 0; if (start2 > 1) preMask = start2 - 1; if (end2 < seq2True) postMask = seq2True - end2; if ((seq2->revCompFlags & rcf_rev) != 0) { tmp = preMask; preMask = postMask; postMask = tmp; } if (preMask != 0) fprintf (f, unsposFmt "%c", preMask, maskCh); opIx = 0; for (i=j=0 ; (i< height)||(j<width) ; ) { run = edit_script_run_of_subs (script, &opIx); fprintf (f, unsposFmt "M", run); i += run; j += run; if ((i < height) || (j < width)) { prevI = i; prevJ = j; edit_script_indel_len (script, &opIx, &i, &j); if (i > prevI) fprintf (f, unsposFmt "D", i - prevI); if (j > prevJ) fprintf (f, unsposFmt "I", j - prevJ); } } if (postMask != 0) fprintf (f, unsposFmt "%c", postMask, maskCh); // print mrnm, mpos, and isize fprintf (f, "\t%s\t%d\t%d\t", "*", 0, 0); // print seq (data from sequence 2) print_query_bases (f, seq2, beg2-1, len2, softMasked); // print qual (if we have no qual data, we print "*") if (seq2->vq == NULL) fprintf (f, "\t%s", "*"); else { fprintf (f, "\t"); print_query_quals (f, seq2, beg2-1, len2, softMasked); } // print tags if (rgTags != NULL) fprintf (f, "\t%s", rgTags); fprintf (f, "\n"); }
void print_maf_match (FILE* f, seq* seq1, unspos pos1, seq* seq2, unspos pos2, unspos length, score s, int withComments) { seqpartition* sp1 = &seq1->partition; seqpartition* sp2 = &seq2->partition; partition* part; u8* s1 = seq1->v + pos1; u8* s2 = seq2->v + pos2; char* name1, *name2, *pref2, *suff1, *suff2; unspos offset1, offset2, start1, start2; unspos startLoc1, startLoc2; unspos seq1Len, seq2Len, seq1True, seq2True; char strand1, strand2; int len1, len2, nameW, startW, lenW; unspos ix; segment seg; unspos numer, denom; if (seq1->revCompFlags != rcf_forward) suicide ("attempt to print - strand or complement for sequence 1 in print_maf_match"); #ifdef debugSeq1Beg if ((pos1 < debugSeq1Beg) || (pos1+length > debugSeq1End)) return; #endif // debugSeq1Beg // report diagonal if (maf_dbgReportDiag) fprintf (f, "# diagonal=" sgnposFmt "\n", diagNumber(pos1,pos2)); if (withComments) { // report identity segment_identity (seq1, pos1, seq2, pos2, length, &numer, &denom); fprintf (f, "# identity=" unsposSlashFmt, numer, denom); if (denom != 0) fprintf (f, " (%.1f%%)", (100.0*numer) / denom); fprintf (f, "\n"); // report coverage seg.pos1 = pos1; seg.pos2 = pos2; seg.length = length; segment_coverage (seq1, seq2, &seg, &numer, &denom); fprintf (f, "# coverage=" unsposSlashFmt, numer, denom); if (denom != 0) fprintf (f, " (%.1f%%)", (100.0*numer) / denom); fprintf (f, "\n"); // report alignment path fprintf (f, "# cigar=" unsposFmt "m\n", length); } // figure out position offsets and names if (sp1->p == NULL) // sequence 1 is not partitioned { name1 = (seq1->useFullNames)? seq1->header : seq1->shortHeader; if ((name1 == NULL) || (name1[0] == 0)) name1 = "seq1"; offset1 = 0; startLoc1 = seq1->startLoc; seq1Len = seq1->len; seq1True = seq1->trueLen; } else // sequence 1 is partitioned { part = lookup_partition (seq1, pos1); name1 = &sp1->pool[part->header]; offset1 = part->sepBefore + 1; startLoc1 = part->startLoc; seq1Len = part->sepAfter - offset1; seq1True = part->trueLen; } if (sp2->p == NULL) // sequence 2 is not partitioned { name2 = (seq2->useFullNames)? seq2->header : seq2->shortHeader; if ((name2 == NULL) || (name2[0] == 0)) name2 = "seq2"; offset2 = 0; startLoc2 = seq2->startLoc; seq2Len = seq2->len; seq2True = seq2->trueLen; } else // sequence 2 is partitioned { part = lookup_partition (seq2, pos2); name2 = &sp2->pool[part->header]; offset2 = part->sepBefore + 1; startLoc2 = part->startLoc; seq2Len = part->sepAfter - offset2; seq2True = part->trueLen; } // print summary line fprintf (f, "a score=" scoreFmt "\n", s); // figure out fields and widths pref2 = ((maf_distinguishNames) && (strcmp (name1, name2) == 0))? "~" : ""; suff1 = rcfSuffix[seq1->revCompFlags]; suff2 = rcfSuffix[seq2->revCompFlags]; if ((seq1->revCompFlags & rcf_rev) == 0) { start1 = pos1 - offset1 + startLoc1; strand1 = '+'; } else { start1 = pos1 - offset1 + seq1True+2 - (startLoc1 + seq1Len); strand1 = '-'; } if ((seq2->revCompFlags & rcf_rev) == 0) { start2 = pos2 - offset2 + startLoc2; strand2 = '+'; } else { start2 = pos2 - offset2 + seq2True+2 - (startLoc2 + seq2Len); strand2 = '-'; } len1 = strlen (name1) + strlen (suff1); len2 = strlen (pref2) + strlen (name2) + strlen (suff2); nameW = (len1 >= len2)? len1 : len2; startW = max_digits (start1, start2); lenW = max_digits (seq1True, seq2True); // print aligning segment of sequence 1 (non-printables are printed as '*' // but such should never be seen unless there is a problem elsewhere) fprintf (f, "s %s%s%*s" unsposStarFmt " " unsposFmt " %c " unsposStarFmt " ", name1, suff1, nameW+1-len1, " ", startW, start1-1, length, strand1, lenW, seq1True); for (ix=0 ; ix<length ; ix++) fprintf (f, "%c", dna_toprint(s1[ix])); fprintf (f, "\n"); // print aligning segment of sequence 2 fprintf (f, "s %s%s%s%*s" unsposStarFmt " " unsposFmt " %c " unsposStarFmt " ", pref2, name2, suff2, nameW+1-len2, " ", startW, start2-1, length, strand2, lenW, seq2True); for (ix=0 ; ix<length ; ix++) fprintf (f, "%c", dna_toprint(s2[ix])); fprintf (f, "\n\n"); }
void print_maf_align (FILE* f, seq* seq1, unspos beg1, unspos end1, seq* seq2, unspos beg2, unspos end2, editscript* script, score s) { seqpartition* sp1 = &seq1->partition; seqpartition* sp2 = &seq2->partition; partition* part; unspos height, width, i, j, run; u32 opIx; u8* p, *q; unspos ix; char* name1, *name2, *pref2, *suff1, *suff2; unspos offset1, offset2, start1, start2; unspos startLoc1, startLoc2; unspos seq1Len, seq2Len, seq1True, seq2True; char strand1, strand2; unspos startI, startJ; int len1, len2, nameW, startW, endW, lenW; #ifdef debugSeq1Beg if ((beg1 < debugSeq1Beg) || (end1 > debugSeq1End)) return; #endif // debugSeq1Beg beg1++; // (internally, we want origin 1, inclusive) beg2++; height = end1 - beg1 + 1; width = end2 - beg2 + 1; // report diagonal if (maf_dbgReportDiag) fprintf (f, "# diagonal=" sgnposFmt "\n", diagNumber(beg1,beg2)); ////////// // figure out position offsets and names ////////// if (sp1->p == NULL) // sequence 1 is not partitioned { name1 = (seq1->useFullNames)? seq1->header : seq1->shortHeader; if ((name1 == NULL) || (name1[0] == 0)) name1 = "seq1"; offset1 = 0; startLoc1 = seq1->startLoc; seq1Len = seq1->len; seq1True = seq1->trueLen; } else // sequence 1 is partitioned { part = lookup_partition (seq1, beg1-1); name1 = &sp1->pool[part->header]; offset1 = part->sepBefore + 1; startLoc1 = part->startLoc; seq1Len = part->sepAfter - offset1; seq1True = part->trueLen; } if (sp2->p == NULL) // sequence 2 is not partitioned { name2 = (seq2->useFullNames)? seq2->header : seq2->shortHeader; if ((name2 == NULL) || (name2[0] == 0)) name2 = "seq2"; offset2 = 0; startLoc2 = seq2->startLoc; seq2Len = seq2->len; seq2True = seq2->trueLen; } else // sequence 2 is partitioned { part = lookup_partition (seq2, beg2-1); name2 = &sp2->pool[part->header]; startLoc2 = part->startLoc; offset2 = part->sepBefore + 1; seq2Len = part->sepAfter - offset2; seq2True = part->trueLen; } ////////// // print summary line ////////// fprintf (f, "a score=" scoreFmt "\n", s); ////////// // print aligning path in sequence 1 ////////// // figure out fields and widths pref2 = ((maf_distinguishNames) && (strcmp (name1, name2) == 0))? "~" : ""; suff1 = rcfSuffix[seq1->revCompFlags]; suff2 = rcfSuffix[seq2->revCompFlags]; if ((seq1->revCompFlags & rcf_rev) == 0) { start1 = beg1-1 - offset1 + startLoc1; strand1 = '+'; } else { start1 = beg1-1 - offset1 + seq1True+2 - (startLoc1 + seq1Len); strand1 = '-'; } if ((seq2->revCompFlags & rcf_rev) == 0) { start2 = beg2-1 - offset2 + startLoc2; strand2 = '+'; } else { start2 = beg2-1 - offset2 + seq2True+2 - (startLoc2 + seq2Len); strand2 = '-'; } len1 = strlen (name1) + strlen (suff1); len2 = strlen (pref2) + strlen (name2) + strlen (suff2); nameW = (len1 >= len2)? len1 : len2; startW = max_digits (start1, start2); endW = max_digits (end1+1-beg1, end2+1-beg2); lenW = max_digits (seq1True, seq2True); // print aligning path in sequence 1 (non-printables are printed as '*' // but such should never be seen unless there is a problem elsewhere) fprintf (f, "s %s%s%*s" unsposStarFmt " " unsposStarFmt " %c " unsposStarFmt " ", name1, suff1, nameW+1-len1, " ", startW, start1-1, endW, end1+1-beg1, strand1, lenW, seq1True); opIx = 0; for (i=j=0 ; (i<height)||(j<width) ; ) { // handle the next run run = edit_script_run_of_subs (script, &opIx); p = seq1->v+beg1+i-1; q = seq2->v+beg2+j-1; for (ix=0 ; ix<run ; ix++) { fprintf (f, "%c", dna_toprint(*p)); p++; q++; } i += run; j += run; // handle the next indel if ((i < height) || (j < width)) { startI = i; p = seq1->v+beg1+i-1; startJ = j; q = seq2->v+beg2+j-1; edit_script_indel_len (script, &opIx, &i, &j); if (i != startI) { for ( ; startI<i ; startI++) { fprintf (f, "%c", dna_toprint(*p)); p++; } } if (j != startJ) { for ( ; startJ<j ; startJ++) { fprintf (f, "-"); q++; } } } } fprintf (f, "\n"); ////////// // print aligning path in sequence 2 ////////// fprintf (f, "s %s%s%s%*s" unsposStarFmt " " unsposStarFmt " %c " unsposStarFmt " ", pref2, name2, suff2, nameW+1-len2, " ", startW, start2-1, endW, end2+1-beg2, strand2, lenW, seq2True); opIx = 0; for (i=j=0 ; (i<height)||(j<width) ; ) { // handle the next run run = edit_script_run_of_subs (script, &opIx); p = seq1->v+beg1+i-1; q = seq2->v+beg2+j-1; for (ix=0 ; ix<run ; ix++) { fprintf (f, "%c", dna_toprint(*q)); p++; q++; } i += run; j += run; // handle the next indel if ((i < height) || (j < width)) { startI = i; p = seq1->v+beg1+i-1; startJ = j; q = seq2->v+beg2+j-1; edit_script_indel_len (script, &opIx, &i, &j); if (i != startI) { for ( ; startI<i ; startI++) { fprintf (f, "-"); p++; } } if (j != startJ) { for ( ; startJ<j ; startJ++) { fprintf (f, "%c", dna_toprint(*q)); q++; } } } } fprintf (f, "\n\n"); }
int main(int argc, char *argv[]) { const char *pname = argv[0]; uint32_t address = 0, read_size = 0, write_size = 0; uint32_t erase_start = 0, erase_size = 0; bool erase = false, do_clear = false; bool program = false, erase_all = false, info = false, do_read = false; bool enable_4B = false, disable_4B = false; bool show_help = false, show_version = false; bool no_action = false, tune = false; char *write_file = NULL, *read_file = NULL, *part_name = NULL; bool ffs_toc_seen = false; int rc; while(1) { static struct option long_opts[] = { {"address", required_argument, NULL, 'a'}, {"size", required_argument, NULL, 's'}, {"partition", required_argument, NULL, 'P'}, {"bmc", no_argument, NULL, 'b'}, {"enable-4B", no_argument, NULL, '4'}, {"disable-4B", no_argument, NULL, '3'}, {"read", required_argument, NULL, 'r'}, {"erase-all", no_argument, NULL, 'E'}, {"erase", no_argument, NULL, 'e'}, {"program", required_argument, NULL, 'p'}, {"force", no_argument, NULL, 'f'}, {"info", no_argument, NULL, 'i'}, {"tune", no_argument, NULL, 't'}, {"dummy", no_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {"debug", no_argument, NULL, 'g'}, {"side", required_argument, NULL, 'S'}, {"toc", required_argument, NULL, 'T'}, {"clear", no_argument, NULL, 'c'} }; int c, oidx = 0; c = getopt_long(argc, argv, "a:s:P:r:43Eep:fdihvbtgS:T:c", long_opts, &oidx); if (c == EOF) break; switch(c) { case 'a': address = strtoul(optarg, NULL, 0); break; case 's': read_size = write_size = strtoul(optarg, NULL, 0); break; case 'P': part_name = strdup(optarg); break; case '4': enable_4B = true; break; case '3': disable_4B = true; break; case 'r': do_read = true; read_file = strdup(optarg); break; case 'E': erase_all = erase = true; break; case 'e': erase = true; break; case 'p': program = true; write_file = strdup(optarg); break; case 'f': must_confirm = false; break; case 'd': must_confirm = false; dummy_run = true; break; case 'i': info = true; break; case 'b': bmc_flash = true; break; case 't': tune = true; break; case 'v': show_version = true; break; case 'h': show_help = show_version = true; break; case 'g': libflash_debug = true; break; case 'S': flash_side = atoi(optarg); break; case 'T': ffs_toc_seen = true; ffs_toc = strtoul(optarg, NULL, 0); break; case 'c': do_clear = true; break; default: exit(1); } } /* Check if we need to access the flash at all (which will * also tune them as a side effect */ no_action = !erase && !program && !info && !do_read && !enable_4B && !disable_4B && !tune && !do_clear; /* Nothing to do, if we didn't already, print usage */ if (no_action && !show_version) show_help = show_version = true; if (show_version) print_version(); if (show_help) print_help(pname); if (no_action) return 0; /* --enable-4B and --disable-4B are mutually exclusive */ if (enable_4B && disable_4B) { fprintf(stderr, "--enable-4B and --disable-4B are mutually" " exclusive !\n"); exit(1); } /* 4B not supported on BMC flash */ if (enable_4B && bmc_flash) { fprintf(stderr, "--enable-4B not supported on BMC flash !\n"); exit(1); } /* partitions not supported on BMC flash */ if (part_name && bmc_flash) { fprintf(stderr, "--partition not supported on BMC flash !\n"); exit(1); } /* part-name and erase-all make no sense together */ if (part_name && erase_all) { fprintf(stderr, "--partition and --erase-all are mutually" " exclusive !\n"); exit(1); } /* Read command should always come with a file */ if (do_read && !read_file) { fprintf(stderr, "Read with no file specified !\n"); exit(1); } /* Program command should always come with a file */ if (program && !write_file) { fprintf(stderr, "Program with no file specified !\n"); exit(1); } /* If both partition and address specified, error out */ if (address && part_name) { fprintf(stderr, "Specify partition or address, not both !\n"); exit(1); } if (do_clear && !part_name) { fprintf(stderr, "--clear only supported on a partition name\n"); exit(1); } /* Explicitly only support two sides */ if (flash_side != 0 && flash_side != 1) { fprintf(stderr, "Unexpected value for --side '%d'\n", flash_side); exit(1); } if (ffs_toc_seen && flash_side) { fprintf(stderr, "--toc and --side are exclusive"); exit(1); } /* If file specified but not size, get size from file */ if (write_file && !write_size) { struct stat stbuf; if (stat(write_file, &stbuf)) { perror("Failed to get file size"); exit(1); } write_size = stbuf.st_size; } if (bmc_flash) { if (arch_flash_bmc(NULL, 1) == -1) { fprintf(stderr, "Can't switch to BMC flash on this architecture\n"); exit(1); } } if (arch_flash_init(&bl, NULL, true)) exit(1); on_exit(exiting, NULL); rc = blocklevel_get_info(bl, &fl_name, &fl_total_size, &fl_erase_granule); if (rc) { fprintf(stderr, "Error %d getting flash info\n", rc); exit(1); } /* If -t is passed, then print a nice message */ if (tune) printf("Flash and controller tuned\n"); /* If read specified and no read_size, use flash size */ if (do_read && !read_size && !part_name) read_size = fl_total_size; /* We have a partition specified, grab the details */ if (part_name) lookup_partition(part_name); /* We have a partition, adjust read/write size if needed */ if (ffsh && ffs_index >= 0) { uint32_t pstart, pmaxsz, pactsize; bool ecc; int rc; rc = ffs_part_info(ffsh, ffs_index, NULL, &pstart, &pmaxsz, &pactsize, &ecc); if (rc) { fprintf(stderr,"Failed to get partition info\n"); exit(1); } if (!ecc && do_clear) { fprintf(stderr, "The partition on which to do --clear " "does not have ECC, are you sure?\n"); check_confirm(); /* Still confirm later on */ must_confirm = true; } /* Read size is obtained from partition "actual" size */ if (!read_size) read_size = pactsize; /* Write size is max size of partition */ if (!write_size) write_size = pmaxsz; /* Crop write size to partition size */ if (write_size > pmaxsz) { printf("WARNING: Size (%d bytes) larger than partition" " (%d bytes), cropping to fit\n", write_size, pmaxsz); write_size = pmaxsz; } /* If erasing, check partition alignment */ if (erase && ((pstart | pmaxsz) & 0xfff)) { fprintf(stderr,"Partition not aligned properly\n"); exit(1); } /* Set address */ address = pstart; } /* Align erase boundaries */ if (erase && !erase_all) { uint32_t mask = 0xfff; uint32_t erase_end; /* Dummy size for erase, will be adjusted later */ if (!write_size) write_size = 1; erase_start = address & ~mask; erase_end = ((address + write_size) + mask) & ~mask; erase_size = erase_end - erase_start; if (erase_start != address || erase_size != write_size) fprintf(stderr, "WARNING: Erase region adjusted" " to 0x%08x..0x%08x\n", erase_start, erase_end); } /* Process commands */ if (enable_4B) enable_4B_addresses(); if (disable_4B) disable_4B_addresses(); if (info) { /* * Don't pass through modfied TOC value if the modification was done * because of --size, but still respect if it came from --toc (we * assume the user knows what they're doing in that case) */ print_flash_info(flash_side ? 0 : ffs_toc); } /* Unlock flash (PNOR only) */ if ((erase || program || do_clear) && !bmc_flash) { need_relock = arch_flash_set_wrprotect(bl, false); if (need_relock == -1) { fprintf(stderr, "Architecture doesn't support write protection on flash\n"); need_relock = 0; exit (1); } } if (do_read) do_read_file(read_file, address, read_size); if (erase_all) erase_chip(); else if (erase) erase_range(erase_start, erase_size, program); if (program) program_file(write_file, address, write_size); if (do_clear) set_ecc(address, write_size); return 0; }